ink_primitives/sol/
bytes.rs1use core::{
16 borrow::Borrow,
17 default::Default,
18 ops::Deref,
19};
20
21use alloy_sol_types::{
22 abi::token::{
23 PackedSeqToken,
24 WordToken,
25 },
26 sol_data,
27 SolType as AlloySolType,
28};
29use ink_prelude::{
30 boxed::Box,
31 vec::Vec,
32};
33use scale::{
34 Decode,
35 Encode,
36};
37#[cfg(feature = "std")]
38use scale_info::TypeInfo;
39
40use crate::sol::{
41 encodable::{
42 DynSizeDefault,
43 Encodable,
44 FixedSizeDefault,
45 },
46 types::SolTokenType,
47 Error,
48 SolDecode,
49 SolEncode,
50 SolTypeDecode,
51 SolTypeEncode,
52};
53
54#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
68#[cfg_attr(feature = "std", derive(TypeInfo))]
69pub struct SolBytes<T: SolBytesType>(pub T);
70
71impl<T: SolBytesType> SolTypeDecode for SolBytes<T> {
73 type AlloyType = T::AlloyType;
74
75 fn detokenize(
76 token: <Self::AlloyType as AlloySolType>::Token<'_>,
77 ) -> Result<Self, Error> {
78 Ok(Self(<T as SolBytesType>::detokenize(token)))
81 }
82}
83
84impl<T: SolBytesType> SolTypeEncode for SolBytes<T> {
85 type AlloyType = T::AlloyType;
86
87 const DEFAULT_VALUE: Self::DefaultType = T::DEFAULT_VALUE;
88
89 fn tokenize(&self) -> Self::TokenType<'_> {
90 <T as SolBytesType>::tokenize(self)
91 }
92}
93
94impl<T: SolBytesType> SolTokenType for SolBytes<T> {
95 type TokenType<'enc> = T::TokenType<'enc>;
96
97 type DefaultType = T::DefaultType;
98}
99
100impl<T: SolBytesType> crate::sol::types::private::Sealed for SolBytes<T> {}
101
102impl<T: SolBytesType> SolDecode for SolBytes<T> {
104 type SolType = SolBytes<T>;
105
106 fn from_sol_type(value: Self::SolType) -> Result<Self, Error> {
107 Ok(value)
108 }
109}
110
111impl<'a, T: SolBytesType + 'a> SolEncode<'a> for SolBytes<T> {
112 type SolType = &'a SolBytes<T>;
113
114 fn to_sol_type(&'a self) -> Self::SolType {
115 self
116 }
117}
118
119impl<T: SolBytesType> Deref for SolBytes<T> {
121 type Target = T;
122
123 fn deref(&self) -> &Self::Target {
124 &self.0
125 }
126}
127
128impl<T: SolBytesType> Borrow<T> for SolBytes<T> {
129 fn borrow(&self) -> &T {
130 &self.0
131 }
132}
133
134impl<T: SolBytesType> AsRef<T> for SolBytes<T> {
135 fn as_ref(&self) -> &T {
136 &self.0
137 }
138}
139
140impl AsRef<[u8]> for SolBytes<Vec<u8>> {
141 fn as_ref(&self) -> &[u8] {
142 &self.0
143 }
144}
145
146pub trait SolBytesType: SolBytesTokenType + private::Sealed {
157 type AlloyType: AlloySolType;
159
160 const DEFAULT_VALUE: Self::DefaultType;
162
163 fn tokenize(&self) -> Self::TokenType<'_>;
165
166 fn detokenize(token: <Self::AlloyType as AlloySolType>::Token<'_>) -> Self;
168
169 fn default() -> Self;
171}
172
173pub trait SolBytesTokenType: private::Sealed {
175 type TokenType<'enc>: Encodable;
177
178 type DefaultType: Encodable;
180}
181
182impl SolBytesType for u8
184where
185 sol_data::ByteCount<1>: sol_data::SupportedFixedBytes,
186{
187 type AlloyType = sol_data::FixedBytes<1>;
188
189 const DEFAULT_VALUE: Self::DefaultType = FixedSizeDefault::WORD;
190
191 fn tokenize(&self) -> <Self::AlloyType as AlloySolType>::Token<'_> {
192 let mut word = [0; 32];
194 word[0] = *self;
195 WordToken::from(word)
196 }
197
198 fn detokenize(token: <Self::AlloyType as AlloySolType>::Token<'_>) -> Self {
199 token.0 .0[0]
202 }
203
204 fn default() -> Self {
205 0u8
206 }
207}
208
209impl SolBytesTokenType for u8
210where
211 sol_data::ByteCount<1>: sol_data::SupportedFixedBytes,
212{
213 type TokenType<'enc> = WordToken;
214
215 type DefaultType = FixedSizeDefault;
216}
217
218impl private::Sealed for u8 {}
219
220impl<const N: usize> SolBytesType for [u8; N]
221where
222 sol_data::ByteCount<N>: sol_data::SupportedFixedBytes,
223{
224 type AlloyType = sol_data::FixedBytes<N>;
225
226 const DEFAULT_VALUE: Self::DefaultType = FixedSizeDefault::WORD;
227
228 fn tokenize(&self) -> Self::TokenType<'_> {
229 let mut word = [0; 32];
232 word[..N].copy_from_slice(self.as_slice());
233 WordToken::from(word)
234 }
235
236 fn detokenize(token: <Self::AlloyType as AlloySolType>::Token<'_>) -> Self {
237 token.0 .0[..N]
242 .try_into()
243 .expect("Expected a slice of N bytes")
244 }
245
246 fn default() -> Self {
247 [0u8; N]
248 }
249}
250
251impl<const N: usize> SolBytesTokenType for [u8; N]
252where
253 sol_data::ByteCount<N>: sol_data::SupportedFixedBytes,
254{
255 type TokenType<'enc> = WordToken;
256
257 type DefaultType = FixedSizeDefault;
258}
259
260impl<const N: usize> private::Sealed for [u8; N] {}
261
262impl SolBytesType for Vec<u8> {
263 type AlloyType = sol_data::Bytes;
264
265 const DEFAULT_VALUE: Self::DefaultType = DynSizeDefault;
266
267 fn tokenize(&self) -> Self::TokenType<'_> {
268 PackedSeqToken(self.as_slice())
271 }
272
273 fn detokenize(token: <Self::AlloyType as AlloySolType>::Token<'_>) -> Self {
274 token.into_vec()
278 }
279
280 fn default() -> Self {
281 Vec::new()
282 }
283}
284
285impl SolBytesTokenType for Vec<u8> {
286 type TokenType<'enc> = PackedSeqToken<'enc>;
287
288 type DefaultType = DynSizeDefault;
289}
290
291impl private::Sealed for Vec<u8> {}
292
293impl SolBytesType for Box<[u8]> {
294 type AlloyType = sol_data::Bytes;
295
296 const DEFAULT_VALUE: Self::DefaultType = DynSizeDefault;
297
298 fn tokenize(&self) -> Self::TokenType<'_> {
299 PackedSeqToken(self.as_ref())
302 }
303
304 fn detokenize(token: <Self::AlloyType as AlloySolType>::Token<'_>) -> Self {
305 Box::from(token.0)
309 }
310
311 fn default() -> Self {
312 <Self as Default>::default()
313 }
314}
315
316impl SolBytesTokenType for Box<[u8]> {
317 type TokenType<'enc> = PackedSeqToken<'enc>;
318
319 type DefaultType = DynSizeDefault;
320}
321
322impl private::Sealed for Box<[u8]> {}
323
324mod private {
325 pub trait Sealed {}
327}