precompile_utils/solidity/codec/
bytes.rs1use super::*;
20use alloc::borrow::ToOwned;
21use sp_core::{ConstU32, Get};
22
23type ConstU32Max = ConstU32<{ u32::MAX }>;
24
25pub type UnboundedBytes = BoundedBytesString<BytesKind, ConstU32Max>;
26pub type BoundedBytes<S> = BoundedBytesString<BytesKind, S>;
27
28pub type UnboundedString = BoundedBytesString<StringKind, ConstU32Max>;
29pub type BoundedString<S> = BoundedBytesString<StringKind, S>;
30
31trait Kind {
32 fn signature() -> String;
33}
34
35#[derive(Clone, Debug, Eq, PartialEq)]
36pub struct BytesKind;
37
38impl Kind for BytesKind {
39 fn signature() -> String {
40 String::from("bytes")
41 }
42}
43
44#[derive(Clone, Debug, Eq, PartialEq)]
45pub struct StringKind;
46
47impl Kind for StringKind {
48 fn signature() -> String {
49 String::from("string")
50 }
51}
52
53#[derive(Debug)]
57pub struct BoundedBytesString<K, S> {
58 data: Vec<u8>,
59 _phantom: PhantomData<(K, S)>,
60}
61
62impl<K: Kind, S: Get<u32>> Clone for BoundedBytesString<K, S> {
63 fn clone(&self) -> Self {
64 Self {
65 data: self.data.clone(),
66 _phantom: PhantomData,
67 }
68 }
69}
70
71impl<K1, S1, K2, S2> PartialEq<BoundedBytesString<K2, S2>> for BoundedBytesString<K1, S1> {
72 fn eq(&self, other: &BoundedBytesString<K2, S2>) -> bool {
73 self.data.eq(&other.data)
74 }
75}
76
77impl<K, S> Eq for BoundedBytesString<K, S> {}
78
79impl<K, S> Default for BoundedBytesString<K, S> {
80 fn default() -> Self {
81 Vec::default().into()
82 }
83}
84
85impl<K, S: Get<u32>> BoundedBytesString<K, S> {
86 pub fn as_bytes(&self) -> &[u8] {
87 &self.data
88 }
89
90 pub fn as_str(&self) -> Result<&str, core::str::Utf8Error> {
91 core::str::from_utf8(&self.data)
92 }
93}
94
95impl<K: Kind, S: Get<u32>> Codec for BoundedBytesString<K, S> {
96 fn read(reader: &mut Reader) -> MayRevert<Self> {
97 let mut inner_reader = reader.read_pointer()?;
98
99 let array_size: usize = inner_reader
101 .read::<U256>()
102 .map_err(|_| RevertReason::read_out_of_bounds("length"))?
103 .try_into()
104 .map_err(|_| RevertReason::value_is_too_large("length"))?;
105
106 if array_size > S::get() as usize {
107 return Err(RevertReason::value_is_too_large("length").into());
108 }
109
110 let range = inner_reader.move_cursor(array_size)?;
112
113 let data = inner_reader
114 .input
115 .get(range)
116 .ok_or_else(|| RevertReason::read_out_of_bounds(K::signature()))?;
117
118 let bytes = Self {
119 data: data.to_owned(),
120 _phantom: PhantomData,
121 };
122
123 Ok(bytes)
124 }
125
126 fn write(writer: &mut Writer, value: Self) {
127 let value: Vec<_> = value.into();
128 let length = value.len();
129
130 let chunks = length / 32;
134 let padded_size = match length % 32 {
135 0 => chunks * 32,
136 _ => (chunks + 1) * 32,
137 };
138
139 let mut value = value.to_vec();
140 value.resize(padded_size, 0);
141
142 writer.write_pointer(
143 Writer::new()
144 .write(U256::from(length))
145 .write_raw_bytes(&value)
146 .build(),
147 );
148 }
149
150 fn has_static_size() -> bool {
151 false
152 }
153
154 fn signature() -> String {
155 K::signature()
156 }
157}
158
159impl<K, S> From<BoundedBytesString<K, S>> for Vec<u8> {
162 fn from(value: BoundedBytesString<K, S>) -> Self {
163 value.data
164 }
165}
166
167impl<K, S> From<Vec<u8>> for BoundedBytesString<K, S> {
168 fn from(value: Vec<u8>) -> Self {
169 Self {
170 data: value,
171 _phantom: PhantomData,
172 }
173 }
174}
175
176impl<K, S> From<&[u8]> for BoundedBytesString<K, S> {
177 fn from(value: &[u8]) -> Self {
178 Self {
179 data: value.to_vec(),
180 _phantom: PhantomData,
181 }
182 }
183}
184
185impl<K, S, const N: usize> From<[u8; N]> for BoundedBytesString<K, S> {
186 fn from(value: [u8; N]) -> Self {
187 Self {
188 data: value.to_vec(),
189 _phantom: PhantomData,
190 }
191 }
192}
193
194impl<K, S, const N: usize> From<&[u8; N]> for BoundedBytesString<K, S> {
195 fn from(value: &[u8; N]) -> Self {
196 Self {
197 data: value.to_vec(),
198 _phantom: PhantomData,
199 }
200 }
201}
202
203impl<K, S> TryFrom<BoundedBytesString<K, S>> for String {
206 type Error = alloc::string::FromUtf8Error;
207
208 fn try_from(value: BoundedBytesString<K, S>) -> Result<Self, Self::Error> {
209 alloc::string::String::from_utf8(value.data)
210 }
211}
212
213impl<K, S> From<&str> for BoundedBytesString<K, S> {
214 fn from(value: &str) -> Self {
215 Self {
216 data: value.as_bytes().into(),
217 _phantom: PhantomData,
218 }
219 }
220}
221
222impl<K, S> From<String> for BoundedBytesString<K, S> {
223 fn from(value: String) -> Self {
224 Self {
225 data: value.as_bytes().into(),
226 _phantom: PhantomData,
227 }
228 }
229}