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}