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