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}