ink_primitives/sol/
bytes.rs1use core::{
16 borrow::Borrow,
17 ops::Deref,
18};
19
20use alloy_sol_types::{
21 abi::token::{
22 PackedSeqToken,
23 WordToken,
24 },
25 sol_data,
26 SolType as AlloySolType,
27};
28use ink_prelude::{
29 boxed::Box,
30 vec::Vec,
31};
32use scale::{
33 Decode,
34 Encode,
35};
36#[cfg(feature = "std")]
37use scale_info::TypeInfo;
38
39use crate::sol::{
40 encodable::{
41 DynSizeDefault,
42 FixedSizeDefault,
43 },
44 types::SolTokenType,
45 utils::{
46 append_non_empty_member_topic_bytes,
47 non_zero_multiple_of_32,
48 },
49 Error,
50 SolDecode,
51 SolEncode,
52 SolTopicEncode,
53 SolTypeDecode,
54 SolTypeEncode,
55};
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode)]
62#[cfg_attr(feature = "std", derive(TypeInfo))]
63#[repr(transparent)]
64pub struct FixedBytes<const N: usize>(pub [u8; N]);
65
66impl<const N: usize> FixedBytes<N> {
67 pub fn from_ref(value: &[u8; N]) -> &Self {
70 unsafe { &*value.as_ptr().cast::<Self>() }
73 }
74}
75
76impl<const N: usize> SolTypeDecode for FixedBytes<N>
78where
79 sol_data::ByteCount<N>: sol_data::SupportedFixedBytes,
80{
81 type AlloyType = sol_data::FixedBytes<N>;
82
83 fn detokenize(
84 token: <Self::AlloyType as AlloySolType>::Token<'_>,
85 ) -> Result<Self, Error> {
86 Ok(Self(
91 token.0 .0[..N]
92 .try_into()
93 .expect("Expected a slice of N bytes"),
94 ))
95 }
96}
97
98impl<const N: usize> SolTypeEncode for FixedBytes<N>
99where
100 sol_data::ByteCount<N>: sol_data::SupportedFixedBytes,
101{
102 type AlloyType = sol_data::FixedBytes<N>;
103
104 const DEFAULT_VALUE: Self::DefaultType = FixedSizeDefault::WORD;
105
106 fn tokenize(&self) -> Self::TokenType<'_> {
107 let mut word = [0; 32];
110 word[..N].copy_from_slice(self.0.as_slice());
111 WordToken::from(word)
112 }
113}
114
115impl<const N: usize> SolTopicEncode for FixedBytes<N>
116where
117 sol_data::ByteCount<N>: sol_data::SupportedFixedBytes,
118{
119 fn encode_topic<H>(&self, _: H) -> [u8; 32]
120 where
121 H: Fn(&[u8], &mut [u8; 32]),
122 {
123 self.tokenize().0 .0
124 }
125
126 fn topic_preimage(&self, buffer: &mut Vec<u8>) {
127 buffer.extend(self.tokenize().0 .0);
128 }
129
130 fn default_topic_preimage(buffer: &mut Vec<u8>) {
131 buffer.extend([0u8; 32]);
132 }
133
134 fn topic_preimage_size(&self) -> usize {
135 Self::default_topic_preimage_size()
136 }
137
138 fn default_topic_preimage_size() -> usize {
139 32
140 }
141}
142
143impl<const N: usize> SolTokenType for FixedBytes<N>
144where
145 sol_data::ByteCount<N>: sol_data::SupportedFixedBytes,
146{
147 type TokenType<'enc> = WordToken;
148
149 type DefaultType = FixedSizeDefault;
150}
151
152impl<const N: usize> crate::sol::types::private::Sealed for FixedBytes<N> where
153 sol_data::ByteCount<N>: sol_data::SupportedFixedBytes
154{
155}
156
157impl<const N: usize> SolDecode for FixedBytes<N>
159where
160 sol_data::ByteCount<N>: sol_data::SupportedFixedBytes,
161{
162 type SolType = FixedBytes<N>;
163
164 fn from_sol_type(value: Self::SolType) -> Result<Self, Error> {
165 Ok(value)
166 }
167}
168
169impl<'a, const N: usize> SolEncode<'a> for FixedBytes<N>
170where
171 sol_data::ByteCount<N>: sol_data::SupportedFixedBytes,
172{
173 type SolType = &'a FixedBytes<N>;
174
175 fn to_sol_type(&'a self) -> Self::SolType {
176 self
177 }
178}
179
180impl<const N: usize> From<[u8; N]> for FixedBytes<N> {
182 fn from(value: [u8; N]) -> Self {
183 Self(value)
184 }
185}
186
187impl From<u8> for FixedBytes<1> {
188 fn from(value: u8) -> Self {
189 Self([value; 1])
190 }
191}
192
193impl<const N: usize> Deref for FixedBytes<N> {
194 type Target = [u8; N];
195
196 fn deref(&self) -> &Self::Target {
197 &self.0
198 }
199}
200
201impl<const N: usize> Borrow<[u8; N]> for FixedBytes<N> {
202 fn borrow(&self) -> &[u8; N] {
203 &self.0
204 }
205}
206
207impl<const N: usize> AsRef<[u8; N]> for FixedBytes<N> {
208 fn as_ref(&self) -> &[u8; N] {
209 &self.0
210 }
211}
212
213#[derive(Debug, Clone, PartialEq, Eq, Default, Encode, Decode)]
218#[cfg_attr(feature = "std", derive(TypeInfo))]
219#[repr(transparent)]
220pub struct DynBytes(pub Vec<u8>);
221
222impl DynBytes {
223 pub const fn new() -> Self {
225 Self(Vec::new())
226 }
227}
228
229impl DynBytes {
230 pub fn from_ref(value: &Vec<u8>) -> &Self {
233 unsafe { &*(value as *const Vec<u8>).cast::<Self>() }
236 }
237}
238
239impl SolTypeDecode for DynBytes {
241 type AlloyType = sol_data::Bytes;
242
243 fn detokenize(
244 token: <Self::AlloyType as AlloySolType>::Token<'_>,
245 ) -> Result<Self, Error> {
246 Ok(Self(token.into_vec()))
250 }
251}
252
253impl SolTypeEncode for DynBytes {
254 type AlloyType = sol_data::Bytes;
255
256 const DEFAULT_VALUE: Self::DefaultType = DynSizeDefault;
257
258 fn tokenize(&self) -> Self::TokenType<'_> {
259 PackedSeqToken(self.0.as_slice())
262 }
263}
264
265impl SolTopicEncode for DynBytes {
266 fn encode_topic<H>(&self, hasher: H) -> [u8; 32]
267 where
268 H: Fn(&[u8], &mut [u8; 32]),
269 {
270 let mut output = [0u8; 32];
271 hasher(self.0.as_slice(), &mut output);
272 output
273 }
274
275 fn topic_preimage(&self, buffer: &mut Vec<u8>) {
276 append_non_empty_member_topic_bytes(self.0.as_slice(), buffer);
277 }
278
279 fn default_topic_preimage(buffer: &mut Vec<u8>) {
280 buffer.extend([0u8; 32]);
281 }
282
283 fn topic_preimage_size(&self) -> usize {
284 non_zero_multiple_of_32(self.0.len())
285 }
286
287 fn default_topic_preimage_size() -> usize {
288 32
289 }
290}
291
292impl SolTokenType for DynBytes {
293 type TokenType<'enc> = PackedSeqToken<'enc>;
294
295 type DefaultType = DynSizeDefault;
296}
297
298impl crate::sol::types::private::Sealed for DynBytes {}
299
300impl SolDecode for DynBytes {
302 type SolType = DynBytes;
303
304 fn from_sol_type(value: Self::SolType) -> Result<Self, Error> {
305 Ok(value)
306 }
307}
308
309impl<'a> SolEncode<'a> for DynBytes {
310 type SolType = &'a DynBytes;
311
312 fn to_sol_type(&'a self) -> Self::SolType {
313 self
314 }
315}
316
317impl From<Vec<u8>> for DynBytes {
319 fn from(value: Vec<u8>) -> Self {
320 Self(value)
321 }
322}
323
324impl From<Box<[u8]>> for DynBytes {
325 fn from(value: Box<[u8]>) -> Self {
326 Self(value.into_vec())
328 }
329}
330
331impl Deref for DynBytes {
332 type Target = [u8];
333
334 fn deref(&self) -> &Self::Target {
335 &self.0
336 }
337}
338
339impl Borrow<[u8]> for DynBytes {
340 fn borrow(&self) -> &[u8] {
341 &self.0
342 }
343}
344
345impl AsRef<[u8]> for DynBytes {
346 fn as_ref(&self) -> &[u8] {
347 &self.0
348 }
349}
350
351#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Encode)]
361#[cfg_attr(feature = "std", derive(TypeInfo))]
362#[repr(transparent)]
363pub struct ByteSlice<'a>(pub &'a [u8]);
364
365impl SolTypeEncode for ByteSlice<'_> {
367 type AlloyType = sol_data::Bytes;
368
369 const DEFAULT_VALUE: Self::DefaultType = DynSizeDefault;
370
371 fn tokenize(&self) -> Self::TokenType<'_> {
372 PackedSeqToken(self.0)
375 }
376}
377
378impl SolTopicEncode for ByteSlice<'_> {
379 fn encode_topic<H>(&self, hasher: H) -> [u8; 32]
380 where
381 H: Fn(&[u8], &mut [u8; 32]),
382 {
383 let mut output = [0u8; 32];
384 hasher(self.0, &mut output);
385 output
386 }
387
388 fn topic_preimage(&self, buffer: &mut Vec<u8>) {
389 append_non_empty_member_topic_bytes(self.0, buffer);
390 }
391
392 fn default_topic_preimage(buffer: &mut Vec<u8>) {
393 buffer.extend([0u8; 32]);
394 }
395
396 fn topic_preimage_size(&self) -> usize {
397 non_zero_multiple_of_32(self.0.len())
398 }
399
400 fn default_topic_preimage_size() -> usize {
401 32
402 }
403}
404
405impl SolTokenType for ByteSlice<'_> {
406 type TokenType<'enc> = PackedSeqToken<'enc>;
407
408 type DefaultType = DynSizeDefault;
409}
410
411impl crate::sol::types::private::Sealed for ByteSlice<'_> {}
412
413impl<'a> SolEncode<'a> for ByteSlice<'a> {
415 type SolType = &'a ByteSlice<'a>;
416
417 fn to_sol_type(&'a self) -> Self::SolType {
418 self
419 }
420}
421
422impl<'a> From<&'a [u8]> for ByteSlice<'a> {
424 fn from(value: &'a [u8]) -> Self {
425 Self(value)
426 }
427}
428
429impl Deref for ByteSlice<'_> {
430 type Target = [u8];
431
432 fn deref(&self) -> &Self::Target {
433 self.0
434 }
435}
436
437impl Borrow<[u8]> for ByteSlice<'_> {
438 fn borrow(&self) -> &[u8] {
439 self.0
440 }
441}
442
443impl AsRef<[u8]> for ByteSlice<'_> {
444 fn as_ref(&self) -> &[u8] {
445 self.0
446 }
447}