cfx_types/
space.rs

1use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream};
2use serde::ser::SerializeMap;
3use serde_derive::{Deserialize, Serialize};
4use std::{
5    ops::{Add, Index, IndexMut},
6    str::FromStr,
7};
8
9#[derive(
10    Eq,
11    PartialEq,
12    Hash,
13    Copy,
14    Clone,
15    Debug,
16    Ord,
17    PartialOrd,
18    Serialize,
19    Deserialize,
20)]
21#[serde(rename_all = "lowercase")]
22pub enum Space {
23    Native,
24    #[serde(rename(serialize = "evm", deserialize = "evm"))]
25    Ethereum,
26}
27
28impl From<Space> for String {
29    fn from(space: Space) -> Self {
30        let str: &'static str = space.into();
31        str.into()
32    }
33}
34
35impl From<Space> for &'static str {
36    fn from(space: Space) -> Self {
37        match space {
38            Space::Native => "native",
39            Space::Ethereum => "evm",
40        }
41    }
42}
43
44impl FromStr for Space {
45    type Err = String;
46
47    fn from_str(s: &str) -> Result<Self, Self::Err> {
48        match s {
49            "native" => Ok(Space::Native),
50            "evm" => Ok(Space::Ethereum),
51            _ => Err(format!("Unrecognized space: {}", s)),
52        }
53    }
54}
55
56impl Encodable for Space {
57    fn rlp_append(&self, s: &mut RlpStream) {
58        let type_int: u8 = match self {
59            Space::Native => 1,
60            Space::Ethereum => 2,
61        };
62        type_int.rlp_append(s)
63    }
64}
65
66impl Decodable for Space {
67    fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
68        match u8::decode(rlp)? {
69            1u8 => Ok(Space::Native),
70            2u8 => Ok(Space::Ethereum),
71            _ => Err(DecoderError::Custom("Unrecognized space byte.")),
72        }
73    }
74}
75
76impl Default for Space {
77    fn default() -> Self { Space::Native }
78}
79
80#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
81pub struct SpaceMap<T> {
82    native: T,
83    evm: T,
84}
85
86impl<T> SpaceMap<T> {
87    pub const fn new(native: T, evm: T) -> Self { SpaceMap { native, evm } }
88
89    #[inline]
90    pub const fn in_space(&self, space: Space) -> &T {
91        match space {
92            Space::Native => &self.native,
93            Space::Ethereum => &self.evm,
94        }
95    }
96
97    #[inline]
98    pub fn in_space_mut(&mut self, space: Space) -> &mut T {
99        match space {
100            Space::Native => &mut self.native,
101            Space::Ethereum => &mut self.evm,
102        }
103    }
104
105    pub fn zip3<B, C>(
106        a: SpaceMap<T>, b: SpaceMap<B>, c: SpaceMap<C>,
107    ) -> SpaceMap<(T, B, C)> {
108        SpaceMap {
109            native: (a.native, b.native, c.native),
110            evm: (a.evm, b.evm, c.evm),
111        }
112    }
113
114    pub fn zip4<B, C, D>(
115        a: SpaceMap<T>, b: SpaceMap<B>, c: SpaceMap<C>, d: SpaceMap<D>,
116    ) -> SpaceMap<(T, B, C, D)> {
117        SpaceMap {
118            native: (a.native, b.native, c.native, d.native),
119            evm: (a.evm, b.evm, c.evm, d.evm),
120        }
121    }
122
123    pub fn map_sum<F: FnMut(&T) -> U, U: Add<U, Output = U>>(
124        &self, mut f: F,
125    ) -> U {
126        f(&self.native) + f(&self.evm)
127    }
128
129    pub const fn size(&self) -> usize { 2 }
130
131    pub fn map_all<U, F: Fn(T) -> U>(self, f: F) -> SpaceMap<U> {
132        SpaceMap {
133            native: f(self.native),
134            evm: f(self.evm),
135        }
136    }
137
138    pub fn apply_all<U, F: FnMut(&mut T) -> U>(
139        &mut self, mut f: F,
140    ) -> SpaceMap<U> {
141        SpaceMap {
142            native: f(&mut self.native),
143            evm: f(&mut self.evm),
144        }
145    }
146}
147
148impl<T> Index<Space> for SpaceMap<T> {
149    type Output = T;
150
151    fn index(&self, space: Space) -> &Self::Output { self.in_space(space) }
152}
153
154impl<T> IndexMut<Space> for SpaceMap<T> {
155    fn index_mut(&mut self, space: Space) -> &mut Self::Output {
156        self.in_space_mut(space)
157    }
158}
159
160impl<T: serde::Serialize> serde::Serialize for SpaceMap<T> {
161    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
162    where S: serde::Serializer {
163        let mut map = serializer.serialize_map(Some(self.size()))?;
164        map.serialize_entry("core", &self.native)?;
165        map.serialize_entry("espace", &self.evm)?;
166        map.end()
167    }
168}