1use crate::{
2 alloc::string::ToString,
3 encoder::{align_up, get_aligned_indices, get_aligned_slice, is_big_endian, Encoder},
4 error::{CodecError, DecodingError},
5};
6use byteorder::ByteOrder;
7use bytes::{Buf, BytesMut};
8use core::{marker::PhantomData, mem::size_of};
9
10impl<B: ByteOrder, const ALIGN: usize, const SOL_MODE: bool, const IS_STATIC: bool>
11 Encoder<B, ALIGN, SOL_MODE, IS_STATIC> for PhantomData<B>
12{
13 const HEADER_SIZE: usize = 0;
14 const IS_DYNAMIC: bool = false;
15
16 fn encode(&self, _buf: &mut BytesMut, _offset: usize) -> Result<(), CodecError> {
17 Ok(())
18 }
19
20 fn decode(_buf: &impl Buf, _offset: usize) -> Result<Self, CodecError> {
21 Ok(PhantomData)
22 }
23
24 fn partial_decode(_buf: &impl Buf, _offset: usize) -> Result<(usize, usize), CodecError> {
25 Ok((0, 0))
26 }
27}
28
29impl<B: ByteOrder, const ALIGN: usize, const SOL_MODE: bool, const IS_STATIC: bool>
30 Encoder<B, ALIGN, SOL_MODE, IS_STATIC> for u8
31{
32 const HEADER_SIZE: usize = size_of::<u8>();
33 const IS_DYNAMIC: bool = false;
34
35 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
36 let word_size =
37 align_up::<ALIGN>(<Self as Encoder<B, ALIGN, SOL_MODE, IS_STATIC>>::HEADER_SIZE);
38
39 if buf.len() < offset + word_size {
40 buf.resize(offset + word_size, 0);
41 }
42
43 let write_to = get_aligned_slice::<B, ALIGN>(buf, offset, 1);
44
45 write_to[0] = *self;
46
47 Ok(())
48 }
49
50 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
51 let word_size =
52 align_up::<ALIGN>(<Self as Encoder<B, ALIGN, SOL_MODE, IS_STATIC>>::HEADER_SIZE);
53
54 if buf.remaining() < offset + word_size {
55 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
56 expected: offset + word_size,
57 found: buf.remaining(),
58 msg: "buf too small to read aligned u8".to_string(),
59 }));
60 }
61
62 let chunk = &buf.chunk()[offset..];
63 let value = if is_big_endian::<B>() {
64 chunk[word_size - 1]
65 } else {
66 chunk[0]
67 };
68
69 Ok(value)
70 }
71
72 fn partial_decode(_buf: &impl Buf, _offset: usize) -> Result<(usize, usize), CodecError> {
73 Ok((
74 0,
75 align_up::<ALIGN>(<Self as Encoder<B, ALIGN, SOL_MODE, IS_STATIC>>::HEADER_SIZE),
76 ))
77 }
78}
79
80impl<B: ByteOrder, const ALIGN: usize, const SOL_MODE: bool, const IS_STATIC: bool>
81 Encoder<B, ALIGN, SOL_MODE, IS_STATIC> for bool
82{
83 const HEADER_SIZE: usize = core::mem::size_of::<bool>();
84 const IS_DYNAMIC: bool = false;
85
86 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
87 let value: u8 = if *self { 1 } else { 0 };
88
89 <u8 as Encoder<B, ALIGN, SOL_MODE, true>>::encode(&value, buf, offset)
90 }
91
92 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
93 let value = <u8 as Encoder<B, ALIGN, SOL_MODE, true>>::decode(buf, offset)?;
94
95 Ok(value != 0)
96 }
97
98 fn partial_decode(_buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
99 Ok((
100 offset,
101 <Self as Encoder<B, ALIGN, SOL_MODE, IS_STATIC>>::HEADER_SIZE,
102 ))
103 }
104}
105
106macro_rules! impl_int {
107 ($typ:ty, $read_method:ident, $write_method:ident) => {
108 impl<B: ByteOrder, const ALIGN: usize, const SOL_MODE: bool, const IS_STATIC: bool>
109 Encoder<B, ALIGN, SOL_MODE, IS_STATIC> for $typ
110 {
111 const HEADER_SIZE: usize = core::mem::size_of::<$typ>();
112 const IS_DYNAMIC: bool = false;
113
114 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
115 let word_size = align_up::<ALIGN>(
116 <Self as Encoder<B, ALIGN, SOL_MODE, IS_STATIC>>::HEADER_SIZE,
117 );
118
119 if buf.len() < offset + word_size {
120 buf.resize(offset + word_size, 0);
121 }
122
123 let (start, end) = get_aligned_indices::<B, ALIGN>(
124 offset,
125 <Self as Encoder<B, ALIGN, SOL_MODE, IS_STATIC>>::HEADER_SIZE,
126 );
127
128 B::$write_method(&mut buf[start..end], *self);
129
130 let fill_val = if *self > 0 { 0x00 } else { 0xFF };
133
134 for i in offset..start {
135 buf[i] = fill_val;
136 }
137
138 B::$write_method(&mut buf[start..end], *self);
139
140 for i in end..(offset + word_size) {
141 buf[i] = fill_val;
142 }
143
144 Ok(())
145 }
146
147 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
148 let word_size = align_up::<ALIGN>(
149 <Self as Encoder<B, ALIGN, SOL_MODE, IS_STATIC>>::HEADER_SIZE,
150 );
151
152 if buf.remaining() < offset + ALIGN {
153 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
154 expected: offset + ALIGN,
155 found: buf.remaining(),
156 msg: "buf too small to decode value".to_string(),
157 }));
158 }
159
160 let chunk = &buf.chunk()[offset..];
161 let value = if is_big_endian::<B>() {
162 B::$read_method(
163 &chunk[word_size
164 - <Self as Encoder<B, ALIGN, SOL_MODE, IS_STATIC>>::HEADER_SIZE
165 ..word_size],
166 )
167 } else {
168 B::$read_method(
169 &chunk[..<Self as Encoder<B, ALIGN, SOL_MODE, IS_STATIC>>::HEADER_SIZE],
170 )
171 };
172
173 Ok(value)
174 }
175
176 fn partial_decode(
177 _buf: &impl Buf,
178 offset: usize,
179 ) -> Result<(usize, usize), CodecError> {
180 Ok((
181 offset,
182 <Self as Encoder<B, ALIGN, SOL_MODE, IS_STATIC>>::HEADER_SIZE,
183 ))
184 }
185 }
186 };
187}
188
189impl_int!(u16, read_u16, write_u16);
190impl_int!(u32, read_u32, write_u32);
191impl_int!(u64, read_u64, write_u64);
192impl_int!(i16, read_i16, write_i16);
193impl_int!(i32, read_i32, write_i32);
194impl_int!(i64, read_i64, write_i64);
195
196impl<T, B: ByteOrder, const ALIGN: usize, const SOL_MODE: bool, const IS_STATIC: bool>
200 Encoder<B, ALIGN, SOL_MODE, IS_STATIC> for Option<T>
201where
202 T: Sized + Encoder<B, ALIGN, SOL_MODE, true> + Default,
203{
204 const HEADER_SIZE: usize = 1 + T::HEADER_SIZE;
205 const IS_DYNAMIC: bool = false;
206
207 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
208 let aligned_header =
209 align_up::<ALIGN>(<Self as Encoder<B, ALIGN, SOL_MODE, IS_STATIC>>::HEADER_SIZE);
210 if buf.len() < offset + aligned_header {
211 buf.resize(offset + aligned_header, 0);
212 }
213 let flag_slice = get_aligned_slice::<B, ALIGN>(buf, offset, 1);
215 flag_slice[0] = if self.is_some() { 1 } else { 0 };
216
217 let inner_offset = offset + ALIGN;
218
219 match self {
220 Some(inner_value) => inner_value.encode(buf, inner_offset)?,
221 None => {
222 let default_value = T::default();
223 default_value.encode(buf, inner_offset)?;
224 }
225 };
226
227 Ok(())
228 }
229
230 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
231 let aligned_header =
232 align_up::<ALIGN>(<Self as Encoder<B, ALIGN, SOL_MODE, IS_STATIC>>::HEADER_SIZE);
233
234 if buf.remaining() < offset + aligned_header {
235 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
236 expected: offset + aligned_header,
237 found: buf.remaining(),
238 msg: "buf too small".to_string(),
239 }));
240 }
241
242 let chunk = &buf.chunk()[offset..];
243 let option_flag = if is_big_endian::<B>() {
244 chunk[aligned_header - 1]
245 } else {
246 chunk[0]
247 };
248
249 let chunk = &buf.chunk()[offset + ALIGN..];
250
251 if option_flag != 0 {
252 let inner_value = T::decode(&chunk, 0)?;
253 Ok(Some(inner_value))
254 } else {
255 Ok(None)
256 }
257 }
258
259 fn partial_decode(buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
260 let aligned_header =
261 align_up::<ALIGN>(<Self as Encoder<B, ALIGN, SOL_MODE, IS_STATIC>>::HEADER_SIZE);
262
263 if buf.remaining() < offset + aligned_header {
264 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
265 expected: offset + aligned_header,
266 found: buf.remaining(),
267 msg: "buf too small".to_string(),
268 }));
269 }
270
271 let chunk = &buf.chunk()[offset..];
272 let option_flag = if is_big_endian::<B>() {
273 chunk[ALIGN - 1]
274 } else {
275 chunk[0]
276 };
277
278 let chunk = &buf.chunk()[offset + ALIGN..];
279
280 if option_flag != 0 {
281 let (_, inner_size) = T::partial_decode(&chunk, 0)?;
282 Ok((offset, aligned_header + inner_size))
283 } else {
284 let aligned_data_size = align_up::<ALIGN>(T::HEADER_SIZE);
285 Ok((offset, aligned_header + aligned_data_size))
286 }
287 }
288}
289
290impl<
291 T,
292 B: ByteOrder,
293 const ALIGN: usize,
294 const SOL_MODE: bool,
295 const N: usize,
296 const IS_STATIC: bool,
297 > Encoder<B, ALIGN, SOL_MODE, IS_STATIC> for [T; N]
298where
299 T: Sized + Encoder<B, ALIGN, SOL_MODE, IS_STATIC> + Default + Copy,
300{
301 const HEADER_SIZE: usize = align_up::<ALIGN>(T::HEADER_SIZE) * N;
302 const IS_DYNAMIC: bool = false;
303
304 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
305 let item_size = align_up::<ALIGN>(T::HEADER_SIZE);
306
307 if buf.len() < offset + (item_size * N) {
308 buf.resize(offset + (item_size * N), 0);
309 }
310
311 for (i, item) in self.iter().enumerate() {
312 item.encode(buf, offset + (item_size * i))?;
313 }
314
315 Ok(())
316 }
317
318 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
319 let item_size = align_up::<ALIGN>(T::HEADER_SIZE);
320 let total_size = offset + (item_size * N);
321
322 if buf.remaining() < total_size {
323 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
324 expected: total_size,
325 found: buf.remaining(),
326 msg: "buf too small to decode [T; N]".to_string(),
327 }));
328 }
329
330 let mut result = [T::default(); N];
331
332 for (i, item) in result.iter_mut().enumerate() {
333 *item = T::decode(buf, offset + (item_size * i))?;
334 }
335
336 Ok(result)
337 }
338
339 fn partial_decode(_buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
340 let item_size = align_up::<ALIGN>(T::HEADER_SIZE);
341 let total_size = item_size * N;
342
343 Ok((offset, total_size))
344 }
345}
346
347#[cfg(test)]
348mod tests {
349 use super::*;
350 use crate::SolidityPackedABI;
351 use byteorder::{BigEndian, LittleEndian};
352 use bytes::{Bytes, BytesMut};
353
354 #[test]
355 fn test_u8_be_encode_decode() {
356 let original: u8 = 1;
357 const ALIGNMENT: usize = 32;
358
359 let mut buf = BytesMut::zeroed(ALIGNMENT);
360
361 println!("Buffer capacity: {}", buf.capacity());
362
363 let encoding_result =
364 <u8 as Encoder<BigEndian, { ALIGNMENT }, false, true>>::encode(&original, &mut buf, 0);
365
366 assert!(encoding_result.is_ok());
367
368 let expected_encoded = "0000000000000000000000000000000000000000000000000000000000000001";
369
370 assert_eq!(hex::encode(&buf), expected_encoded);
371
372 let buf_for_decode = buf.clone().freeze();
373 let decoded =
374 <u8 as Encoder<BigEndian, { ALIGNMENT }, false, true>>::decode(&buf_for_decode, 0)
375 .unwrap();
376
377 assert_eq!(original, decoded);
378 println!("encoded: {:?}", buf);
379
380 let partial_decoded =
381 <u8 as Encoder<BigEndian, { ALIGNMENT }, false, true>>::partial_decode(
382 &buf.clone().freeze(),
383 0,
384 )
385 .unwrap();
386 assert_eq!(partial_decoded, (0, ALIGNMENT));
387 }
388
389 #[test]
390 fn test_u8_le_encode_decode() {
391 let original: u8 = 1;
392 const ALIGNMENT: usize = 32;
393 let mut buf = BytesMut::zeroed(ALIGNMENT);
394
395 println!("Buffer capacity: {}", buf.capacity());
396
397 let encoding_result = <u8 as Encoder<LittleEndian, { ALIGNMENT }, false, true>>::encode(
398 &original, &mut buf, 0,
399 );
400
401 assert!(encoding_result.is_ok());
402
403 let expected_encoded = "0100000000000000000000000000000000000000000000000000000000000000";
404
405 let encoded = buf.freeze();
406 println!("Encoded: {:?}", encoded);
407 assert_eq!(hex::encode(&encoded), expected_encoded);
408
409 let decoded =
410 <u8 as Encoder<LittleEndian, { ALIGNMENT }, false, true>>::decode(&encoded, 0).unwrap();
411 println!("Decoded: {}", decoded);
412
413 assert_eq!(original, decoded);
414
415 let partial_decoded =
416 <u8 as Encoder<LittleEndian, { ALIGNMENT }, false, true>>::partial_decode(&encoded, 0)
417 .unwrap();
418
419 assert_eq!(partial_decoded, (0, 32));
420 }
421
422 #[test]
423 fn test_bool_be_encode_decode() {
424 let original: bool = true;
425 const ALIGNMENT: usize = 32;
426
427 let mut buf = BytesMut::zeroed(ALIGNMENT);
428
429 println!("Buffer capacity: {}", buf.capacity());
430
431 let encoding_result = <bool as Encoder<BigEndian, { ALIGNMENT }, false, true>>::encode(
432 &original, &mut buf, 0,
433 );
434
435 assert!(encoding_result.is_ok());
436
437 let expected_encoded = "0000000000000000000000000000000000000000000000000000000000000001";
438
439 assert_eq!(hex::encode(&buf), expected_encoded);
440
441 let buf_for_decode = buf.clone().freeze();
442 let decoded =
443 <bool as Encoder<BigEndian, { ALIGNMENT }, false, true>>::decode(&buf_for_decode, 0)
444 .unwrap();
445
446 assert_eq!(original, decoded);
447 println!("encoded: {:?}", buf);
448
449 let partial_decoded =
450 <bool as Encoder<BigEndian, { ALIGNMENT }, false, true>>::partial_decode(
451 &buf.clone().freeze(),
452 0,
453 )
454 .unwrap();
455 assert_eq!(partial_decoded, (0, 1));
456 }
457
458 #[test]
459 fn test_bool_le_encode_decode() {
460 let original: bool = true;
461 const ALIGNMENT: usize = 32;
462
463 let mut buf = BytesMut::zeroed(ALIGNMENT);
464
465 println!("Buffer capacity: {}", buf.capacity());
466
467 let encoding_result = <bool as Encoder<LittleEndian, { ALIGNMENT }, false, true>>::encode(
468 &original, &mut buf, 0,
469 );
470
471 assert!(encoding_result.is_ok());
472
473 let expected_encoded = "0100000000000000000000000000000000000000000000000000000000000000";
474
475 assert_eq!(hex::encode(&buf), expected_encoded);
476
477 let buf_for_decode = buf.clone().freeze();
478 let decoded =
479 <bool as Encoder<LittleEndian, { ALIGNMENT }, false, true>>::decode(&buf_for_decode, 0)
480 .unwrap();
481
482 assert_eq!(original, decoded);
483 println!("encoded: {:?}", buf);
484
485 let partial_decoded =
486 <bool as Encoder<LittleEndian, { ALIGNMENT }, false, true>>::partial_decode(
487 &buf.clone().freeze(),
488 0,
489 )
490 .unwrap();
491 assert_eq!(partial_decoded, (0, 1));
492 }
493
494 #[test]
495 fn test_u32_encode_decode_le() {
496 let original: u32 = 0x12345678;
497 let mut buf = BytesMut::new();
498
499 <u32 as Encoder<LittleEndian, 8, false, true>>::encode(&original, &mut buf, 0).unwrap();
500
501 println!("Encoded: {:?}", buf);
502
503 assert_eq!(buf.to_vec(), vec![0x78, 0x56, 0x34, 0x12, 0, 0, 0, 0]);
504
505 let buf_for_decode = buf.freeze();
506 let decoded =
507 <u32 as Encoder<LittleEndian, 8, false, true>>::decode(&buf_for_decode, 0).unwrap();
508
509 assert_eq!(original, decoded);
510 }
511
512 #[test]
513 fn test_u32_encode_decode_be() {
514 let original: u32 = 0x12345678;
515 let mut buf = BytesMut::new();
516
517 <u32 as Encoder<BigEndian, 8, false, true>>::encode(&original, &mut buf, 0).unwrap();
518
519 let encoded = buf.freeze();
520 println!("{:?}", hex::encode(&encoded));
521 assert_eq!(
522 &encoded,
523 &vec![0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78]
524 );
525
526 let decoded = <u32 as Encoder<BigEndian, 8, false, true>>::decode(&encoded, 0).unwrap();
527 println!("Decoded: {}", decoded);
528
529 assert_eq!(original, decoded);
530 }
531
532 #[test]
533 fn test_i64_encode_decode_be() {
534 let original: i64 = 0x1234567890ABCDEF;
535 let mut buf = BytesMut::new();
536
537 <i64 as Encoder<BigEndian, 8, false, true>>::encode(&original, &mut buf, 0).unwrap();
538
539 let encoded = buf.freeze();
540 println!("Encoded: {:?}", hex::encode(&encoded));
541 assert_eq!(
542 &encoded,
543 &vec![0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]
544 );
545
546 let decoded = <i64 as Encoder<BigEndian, 8, false, true>>::decode(&encoded, 0).unwrap();
547 println!("Decoded: {}", decoded);
548
549 assert_eq!(original, decoded);
550 }
551 #[test]
552 fn test_u32_wasm_abi_encode_decode() {
553 let original: u32 = 0x12345678;
554 let mut buf = BytesMut::new();
555
556 <u32 as Encoder<LittleEndian, 4, false, true>>::encode(&original, &mut buf, 0).unwrap();
558
559 assert_eq!(buf.to_vec(), vec![0x78, 0x56, 0x34, 0x12]);
561
562 let decoded = <u32 as Encoder<LittleEndian, 4, false, true>>::decode(&buf, 0).unwrap();
564
565 assert_eq!(original, decoded);
567 }
568
569 #[test]
570 fn test_u32_solidity_abi_encode_decode() {
571 let original: u32 = 0x12345678;
572 let mut buf = BytesMut::new();
573
574 <u32 as Encoder<BigEndian, 32, true, true>>::encode(&original, &mut buf, 0).unwrap();
576
577 let expected = vec![
579 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
580 0x12, 0x34, 0x56, 0x78,
581 ];
582 assert_eq!(buf.to_vec(), expected);
583
584 let decoded = <u32 as Encoder<BigEndian, 32, true, true>>::decode(&buf, 0).unwrap();
586
587 assert_eq!(original, decoded);
589 }
590
591 #[test]
592 fn test_option_u32_encode_decode() {
593 let original: Option<u32> = Some(0x12345678);
594 let mut buf = BytesMut::with_capacity(8);
595
596 let ok =
597 <Option<u32> as Encoder<LittleEndian, 4, false, true>>::encode(&original, &mut buf, 0);
598 assert!(ok.is_ok());
599
600 let encoded = buf.freeze();
601 println!("Encoded: {:?}", &encoded.to_vec());
602 assert_eq!(
603 encoded,
604 Bytes::from_static(&[0x01, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12])
605 );
606
607 let decoded = <Option<u32> as Encoder<LittleEndian, 4, false, true>>::decode(&encoded, 0);
608
609 assert_eq!(original, decoded.unwrap());
610 }
611
612 #[test]
613 fn test_u8_array_encode_decode_le_with_alignment() {
614 let original: [u8; 5] = [1, 2, 3, 4, 5];
615 let mut buf = BytesMut::new();
616
617 <[u8; 5] as Encoder<LittleEndian, 4, false, true>>::encode(&original, &mut buf, 0).unwrap();
618
619 let encoded = buf.freeze();
620 println!("Encoded: {:?}", hex::encode(&encoded));
621
622 assert_eq!(
624 &encoded.to_vec(),
625 &[
626 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00 ]
632 );
633
634 println!("Encoded: {:?}", encoded.to_vec());
635 println!("encoded len: {}", encoded.len());
636 let decoded =
637 <[u8; 5] as Encoder<LittleEndian, 4, false, true>>::decode(&encoded, 0).unwrap();
638 println!("Decoded: {:?}", decoded);
639
640 assert_eq!(original, decoded);
641 }
642
643 #[test]
644 fn test_packed_encoding() {
645 let value1: u32 = 0x12345678;
646 let value2: u16 = 0x9ABC;
647 let value3: u8 = 0xDE;
648 let mut buf = BytesMut::new();
649
650 SolidityPackedABI::<u32>::encode(&value1, &mut buf, 0).unwrap();
651 SolidityPackedABI::<u16>::encode(&value2, &mut buf, 4).unwrap();
652 SolidityPackedABI::<u8>::encode(&value3, &mut buf, 6).unwrap();
653
654 assert_eq!(buf.to_vec(), vec![0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE]);
655 }
656
657 #[test]
658 fn test_packed_array() {
659 let arr: [u16; 3] = [0x1234, 0x5678, 0x9ABC];
660 let mut buf = BytesMut::new();
661
662 SolidityPackedABI::<[u16; 3]>::encode(&arr, &mut buf, 0).unwrap();
664
665 assert_eq!(buf.to_vec(), vec![0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC]);
666
667 let decoded = SolidityPackedABI::<[u16; 3]>::decode(&buf, 0).unwrap();
668 assert_eq!(arr, decoded);
669 }
670}