1use crate::{
2 alloc::string::ToString,
3 bytes_codec::{read_bytes, read_bytes_header, write_bytes},
4 encoder::{align_up, get_aligned_slice, is_big_endian, write_u32_aligned, Encoder},
5 error::{CodecError, DecodingError},
6};
7use alloc::string::String;
8use alloy_primitives::{Address, Bytes, FixedBytes, Signed, Uint};
9use byteorder::ByteOrder;
10use bytes::{Buf, BytesMut};
11
12impl<B: ByteOrder, const ALIGN: usize> Encoder<B, ALIGN, true, false> for Bytes {
13 const HEADER_SIZE: usize = 32;
14 const IS_DYNAMIC: bool = true;
15
16 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
20 let aligned_header_size =
21 align_up::<32>(<Self as Encoder<B, ALIGN, true, false>>::HEADER_SIZE);
22
23 if buf.len() < offset + aligned_header_size {
25 buf.resize(offset + aligned_header_size, 0);
26 }
27
28 write_u32_aligned::<B, ALIGN>(buf, offset, buf.len() as u32);
30
31 let _ = write_bytes::<B, ALIGN, true>(buf, buf.len(), self, self.len() as u32);
33
34 if !buf.len().is_multiple_of(ALIGN) {
36 let padding = ALIGN - (buf.len() % ALIGN);
37 buf.resize(buf.len() + padding, 0);
38 }
39
40 Ok(())
41 }
42
43 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
46 Ok(Self::from(read_bytes::<B, ALIGN, true>(buf, offset)?))
47 }
48
49 fn partial_decode(buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
52 read_bytes_header::<B, ALIGN, true>(buf, offset)
53 }
54}
55
56impl<B: ByteOrder, const ALIGN: usize> Encoder<B, ALIGN, false, false> for Bytes {
57 const HEADER_SIZE: usize = size_of::<u32>() * 2;
58 const IS_DYNAMIC: bool = true;
59
60 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
64 let aligned_el_size = align_up::<ALIGN>(4);
65
66 if buf.len() < offset + aligned_el_size {
68 buf.resize(offset + aligned_el_size, 0);
69 }
70
71 let _ = write_bytes::<B, ALIGN, false>(buf, offset, self, self.len() as u32);
72
73 if !buf.len().is_multiple_of(ALIGN) {
75 let padding = ALIGN - (buf.len() % ALIGN);
76 buf.resize(buf.len() + padding, 0);
77 }
78
79 Ok(())
80 }
81
82 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
85 Ok(Self::from(read_bytes::<B, ALIGN, false>(buf, offset)?))
86 }
87
88 fn partial_decode(buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
91 read_bytes_header::<B, ALIGN, false>(buf, offset)
92 }
93}
94
95impl<B: ByteOrder, const ALIGN: usize> Encoder<B, ALIGN, true, false> for String {
96 const HEADER_SIZE: usize = <Bytes as Encoder<B, ALIGN, true, false>>::HEADER_SIZE;
97 const IS_DYNAMIC: bool = true;
98
99 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
100 <Bytes as Encoder<B, ALIGN, true, false>>::encode(
101 &Bytes::copy_from_slice(self.as_bytes()),
102 buf,
103 offset,
104 )
105 }
106
107 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
108 let bytes = <Bytes as Encoder<B, ALIGN, true, false>>::decode(buf, offset)?;
109 String::from_utf8(bytes.to_vec()).map_err(|_| {
110 CodecError::Decoding(DecodingError::InvalidData(
111 "failed to decode string from utf8".to_string(),
112 ))
113 })
114 }
115
116 fn partial_decode(buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
117 <Bytes as Encoder<B, ALIGN, true, false>>::partial_decode(buf, offset)
118 }
119}
120
121impl<B: ByteOrder, const ALIGN: usize> Encoder<B, ALIGN, false, false> for String {
122 const HEADER_SIZE: usize = <Bytes as Encoder<B, ALIGN, false, false>>::HEADER_SIZE;
123 const IS_DYNAMIC: bool = true;
124
125 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
126 <Bytes as Encoder<B, ALIGN, false, false>>::encode(
127 &Bytes::copy_from_slice(self.as_bytes()),
128 buf,
129 offset,
130 )
131 }
132
133 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
134 let bytes = <Bytes as Encoder<B, ALIGN, false, false>>::decode(buf, offset)?;
135 String::from_utf8(bytes.to_vec()).map_err(|_| {
136 CodecError::Decoding(DecodingError::InvalidData(
137 "failed to decode string from utf8".to_string(),
138 ))
139 })
140 }
141
142 fn partial_decode(buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
143 <Bytes as Encoder<B, ALIGN, false, false>>::partial_decode(buf, offset)
144 }
145}
146
147impl<const N: usize, B: ByteOrder, const ALIGN: usize, const IS_STATIC: bool>
148 Encoder<B, ALIGN, false, IS_STATIC> for FixedBytes<N>
149{
150 const HEADER_SIZE: usize = N;
151 const IS_DYNAMIC: bool = false;
152
153 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
156 let slice = get_aligned_slice::<B, ALIGN>(buf, offset, N);
157 slice.copy_from_slice(self.as_ref());
158 Ok(())
159 }
160
161 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
164 if buf.remaining() < offset + N {
165 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
166 expected: offset + N,
167 found: buf.remaining(),
168 msg: "Buffer too small to decode FixedBytes".to_string(),
169 }));
170 }
171 let data = buf.chunk()[offset..offset + N].to_vec();
172 Ok(FixedBytes::from_slice(&data))
173 }
174
175 fn partial_decode(_buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
178 let aligned_offset = align_up::<ALIGN>(offset);
179 Ok((aligned_offset, N))
180 }
181}
182
183impl<const N: usize, B: ByteOrder, const ALIGN: usize, const IS_STATIC: bool>
184 Encoder<B, ALIGN, true, IS_STATIC> for FixedBytes<N>
185{
186 const HEADER_SIZE: usize = 32; const IS_DYNAMIC: bool = false;
188
189 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
192 let slice = get_aligned_slice::<B, 32>(buf, offset, 32);
193 slice[..N].copy_from_slice(self.as_ref());
194 slice[N..].fill(0);
196 Ok(())
197 }
198
199 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
203 let offset = align_up::<32>(offset); if buf.remaining() < offset + 32 {
205 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
206 expected: offset + 32,
207 found: buf.remaining(),
208 msg: "Buffer too small to decode FixedBytes".to_string(),
209 }));
210 }
211 let data = buf.chunk()[offset..offset + N].to_vec();
212 Ok(FixedBytes::from_slice(&data))
213 }
214
215 fn partial_decode(_buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
218 Ok((offset, 32))
219 }
220}
221
222macro_rules! impl_evm_fixed {
223 ($type:ty) => {
224 impl<B: ByteOrder, const ALIGN: usize, const IS_STATIC: bool>
225 Encoder<B, ALIGN, false, IS_STATIC> for $type
226 {
227 const HEADER_SIZE: usize = <$type>::len_bytes();
228 const IS_DYNAMIC: bool = false;
229
230 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
233 let slice = get_aligned_slice::<B, ALIGN>(buf, offset, <$type>::len_bytes());
234 slice.copy_from_slice(self.as_ref());
235 Ok(())
236 }
237
238 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
241 let size = <$type>::len_bytes();
242 if buf.remaining() < offset + size {
243 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
244 expected: offset + size,
245 found: buf.remaining(),
246 msg: "Buffer too small to decode fixed bytes".to_string(),
247 }));
248 }
249 let data = buf.chunk()[offset..offset + size].to_vec();
250 Ok(<$type>::from_slice(&data))
251 }
252
253 fn partial_decode(
256 _buf: &impl Buf,
257 offset: usize,
258 ) -> Result<(usize, usize), CodecError> {
259 Ok((offset, <$type>::len_bytes()))
260 }
261 }
262
263 impl<B: ByteOrder, const ALIGN: usize, const IS_STATIC: bool>
264 Encoder<B, ALIGN, true, IS_STATIC> for $type
265 {
266 const HEADER_SIZE: usize = 32; const IS_DYNAMIC: bool = false;
268
269 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
273 let slice = get_aligned_slice::<B, 32>(buf, offset, 32);
274 let size = <$type>::len_bytes();
275 slice[..32 - size].fill(0);
277 slice[32 - size..].copy_from_slice(self.as_ref());
279 Ok(())
280 }
281
282 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
286 let size = <$type>::len_bytes();
287 if buf.remaining() < offset + 32 {
288 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
289 expected: offset + 32,
290 found: buf.remaining(),
291 msg: "Buffer too small to decode fixed bytes".to_string(),
292 }));
293 }
294 let data = buf.chunk()[offset + 32 - size..offset + 32].to_vec();
295 Ok(<$type>::from_slice(&data))
296 }
297
298 fn partial_decode(
301 _buf: &impl Buf,
302 offset: usize,
303 ) -> Result<(usize, usize), CodecError> {
304 Ok((offset, 32))
305 }
306 }
307 };
308}
309
310impl_evm_fixed!(Address);
311
312impl<
313 const BITS: usize,
314 const LIMBS: usize,
315 B: ByteOrder,
316 const ALIGN: usize,
317 const IS_STATIC: bool,
318 > Encoder<B, ALIGN, false, IS_STATIC> for Uint<BITS, LIMBS>
319{
320 const HEADER_SIZE: usize = Self::BYTES;
321 const IS_DYNAMIC: bool = false;
322
323 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
324 let word_size = align_up::<ALIGN>(Self::BYTES);
325
326 let slice = get_aligned_slice::<B, ALIGN>(buf, offset, word_size);
327
328 let bytes = if is_big_endian::<B>() {
329 self.to_be_bytes_vec()
330 } else {
331 self.to_le_bytes_vec()
332 };
333
334 slice[..Self::BYTES].copy_from_slice(&bytes);
335
336 Ok(())
337 }
338
339 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
340 let word_size = align_up::<ALIGN>(Self::BYTES);
341
342 if buf.remaining() < offset + word_size {
343 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
344 expected: offset + word_size,
345 found: buf.remaining(),
346 msg: "buf too small to read Uint".to_string(),
347 }));
348 }
349
350 let chunk = &buf.chunk()[offset..offset + word_size];
351 let value_slice = &chunk[..Self::BYTES];
352
353 let value = if is_big_endian::<B>() {
354 Self::from_be_slice(value_slice)
355 } else {
356 Self::from_le_slice(value_slice)
357 };
358
359 Ok(value)
360 }
361
362 fn partial_decode(_buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
363 let word_size = align_up::<ALIGN>(Self::BYTES);
364 Ok((offset, word_size))
365 }
366}
367
368impl<
369 const BITS: usize,
370 const LIMBS: usize,
371 B: ByteOrder,
372 const ALIGN: usize,
373 const IS_STATIC: bool,
374 > Encoder<B, ALIGN, true, IS_STATIC> for Uint<BITS, LIMBS>
375{
376 const HEADER_SIZE: usize = 32; const IS_DYNAMIC: bool = false;
378
379 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
380 let slice = get_aligned_slice::<B, 32>(buf, offset, 32);
381
382 let bytes = if is_big_endian::<B>() {
383 self.to_be_bytes_vec()
384 } else {
385 self.to_le_bytes_vec()
386 };
387
388 slice[32 - Self::BYTES..].copy_from_slice(&bytes);
390 slice[..32 - Self::BYTES].fill(0); Ok(())
393 }
394
395 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
396 if buf.remaining() < offset + 32 {
397 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
398 expected: offset + 32,
399 found: buf.remaining(),
400 msg: "buf too small to read Uint".to_string(),
401 }));
402 }
403
404 let chunk = &buf.chunk()[offset..offset + 32];
405 let value_slice = &chunk[32 - Self::BYTES..];
406
407 let value = if is_big_endian::<B>() {
408 Self::from_be_slice(value_slice)
409 } else {
410 Self::from_le_slice(value_slice)
411 };
412
413 Ok(value)
414 }
415
416 fn partial_decode(_buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
417 Ok((offset, 32))
418 }
419}
420
421impl<
422 const BITS: usize,
423 const LIMBS: usize,
424 B: ByteOrder,
425 const ALIGN: usize,
426 const IS_STATIC: bool,
427 > Encoder<B, ALIGN, false, IS_STATIC> for Signed<BITS, LIMBS>
428{
429 const HEADER_SIZE: usize = Self::BYTES;
430 const IS_DYNAMIC: bool = false;
431
432 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
433 let word_size = align_up::<ALIGN>(Self::BYTES);
434
435 let slice = get_aligned_slice::<B, ALIGN>(buf, offset, word_size);
436
437 let bytes = if is_big_endian::<B>() {
438 self.into_raw().to_be_bytes_vec()
439 } else {
440 self.into_raw().to_le_bytes_vec()
441 };
442
443 slice[..Self::BYTES].copy_from_slice(&bytes);
444
445 Ok(())
446 }
447
448 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
449 let word_size = align_up::<ALIGN>(Self::BYTES);
450
451 if buf.remaining() < offset + word_size {
452 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
453 expected: offset + word_size,
454 found: buf.remaining(),
455 msg: "buf too small to read Signed".to_string(),
456 }));
457 }
458
459 let chunk = &buf.chunk()[offset..offset + word_size];
460 let value_slice = &chunk[..Self::BYTES];
461
462 let value = if is_big_endian::<B>() {
463 Self::from_raw(Uint::<BITS, LIMBS>::from_be_slice(value_slice))
464 } else {
465 Self::from_raw(Uint::<BITS, LIMBS>::from_le_slice(value_slice))
466 };
467
468 Ok(value)
469 }
470
471 fn partial_decode(_buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
472 let word_size = align_up::<ALIGN>(Self::BYTES);
473 Ok((offset, word_size))
474 }
475}
476
477impl<
478 const BITS: usize,
479 const LIMBS: usize,
480 B: ByteOrder,
481 const ALIGN: usize,
482 const IS_STATIC: bool,
483 > Encoder<B, ALIGN, true, IS_STATIC> for Signed<BITS, LIMBS>
484{
485 const HEADER_SIZE: usize = 32; const IS_DYNAMIC: bool = false;
487
488 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
489 let slice = get_aligned_slice::<B, 32>(buf, offset, 32);
490
491 let bytes = if is_big_endian::<B>() {
492 self.into_raw().to_be_bytes_vec()
493 } else {
494 self.into_raw().to_le_bytes_vec()
495 };
496
497 slice[32 - Self::BYTES..].copy_from_slice(&bytes);
499
500 if self.is_negative() {
504 slice[..32 - Self::BYTES].fill(0xFF);
505 } else {
506 slice[..32 - Self::BYTES].fill(0);
507 }
508
509 Ok(())
510 }
511
512 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
513 if buf.remaining() < offset + 32 {
514 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
515 expected: offset + 32,
516 found: buf.remaining(),
517 msg: "buf too small to read Signed".to_string(),
518 }));
519 }
520
521 let chunk = &buf.chunk()[offset..offset + 32];
522 let value_slice = &chunk[32 - Self::BYTES..];
523
524 let value = if is_big_endian::<B>() {
525 Self::from_raw(Uint::<BITS, LIMBS>::from_be_slice(value_slice))
526 } else {
527 Self::from_raw(Uint::<BITS, LIMBS>::from_le_slice(value_slice))
528 };
529
530 Ok(value)
531 }
532
533 fn partial_decode(_buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
534 Ok((offset, 32))
535 }
536}
537
538#[cfg(test)]
539mod tests {
540 use super::*;
541 use crate::{
542 byteorder::{BE, LE},
543 CompactABI,
544 SolidityABI,
545 };
546 #[cfg(test)]
547 use alloy_primitives::{Address, U256};
548 use alloy_primitives::{I128, I256};
549 use byteorder::{BigEndian, LittleEndian};
550 use bytes::BytesMut;
551
552 #[test]
553 fn test_write_to_existing_buf() {
554 let existing_data = &[
555 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, ];
561 let mut buf = BytesMut::new();
562 buf.extend_from_slice(existing_data);
563
564 let original = Bytes::from_static(b"Hello, World");
565 let _result =
567 write_bytes::<BigEndian, 8, false>(&mut buf, 16, &original, original.len() as u32);
568
569 let expected = [
570 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 12, 72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, ];
577
578 assert_eq!(buf.to_vec(), expected);
579
580 let encoded = buf.freeze();
581 println!("Encoded Bytes: {:?}", encoded.to_vec());
582
583 let decoded = read_bytes::<BigEndian, 8, false>(&encoded, 0).unwrap();
584
585 println!("Decoded Bytes: {:?}", decoded.to_vec());
586 assert_eq!(decoded.to_vec(), original.to_vec());
587 }
588
589 #[test]
590 fn test_address_encode_decode() {
591 let original = Address::from([0x42; 20]);
592 let mut buf = BytesMut::new();
593
594 <Address as Encoder<LittleEndian, 1, false, true>>::encode(&original, &mut buf, 0).unwrap();
595
596 let encoded = buf.freeze();
597 println!("Encoded Address: {}", hex::encode(&encoded));
598
599 let decoded =
600 <Address as Encoder<LittleEndian, 1, false, true>>::decode(&encoded, 0).unwrap();
601
602 assert_eq!(original, decoded);
603 }
604 #[test]
605 fn test_address_encode_decode_aligned() {
606 let original = Address::from([0x42; 20]);
607 let mut buf = BytesMut::new();
608
609 <Address as Encoder<LittleEndian, 32, true, true>>::encode(&original, &mut buf, 0).unwrap();
610
611 let encoded = buf.freeze();
612 println!("Encoded Address: {}", hex::encode(&encoded));
613
614 let decoded =
615 <Address as Encoder<LittleEndian, 32, true, true>>::decode(&encoded, 0).unwrap();
616
617 assert_eq!(original, decoded);
618 }
619
620 #[test]
621 fn test_uint_encode_decode_le() {
622 let original = U256::from(0x1234567890abcdef_u64);
623 let mut buf = BytesMut::new();
624
625 <U256 as Encoder<LittleEndian, 4, false, true>>::encode(&original, &mut buf, 0).unwrap();
626
627 let encoded = buf.freeze();
628 println!("Encoded U256 (LE): {}", hex::encode(&encoded));
629 let expected_encoded = "efcdab9078563412000000000000000000000000000000000000000000000000";
630 assert_eq!(hex::encode(&encoded), expected_encoded);
631
632 let decoded = <U256 as Encoder<LittleEndian, 4, false, true>>::decode(&encoded, 0).unwrap();
633
634 assert_eq!(original, decoded);
635 }
636
637 #[test]
638 fn test_uint_encode_decode_be() {
639 let original = U256::from(0x1234567890abcdef_u64);
640 let mut buf = BytesMut::new();
641
642 <U256 as Encoder<BigEndian, 4, false, true>>::encode(&original, &mut buf, 0).unwrap();
643
644 let encoded = buf.freeze();
645 println!("Encoded U256 (BE): {}", hex::encode(&encoded));
646 let expected_encoded = "0000000000000000000000000000000000000000000000001234567890abcdef";
647 assert_eq!(hex::encode(&encoded), expected_encoded);
648
649 let decoded = <U256 as Encoder<BigEndian, 4, false, true>>::decode(&encoded, 0).unwrap();
650
651 assert_eq!(original, decoded);
652 }
653 #[test]
654 fn test_string_encoding_solidity() {
655 let original = "Hello, World!!".to_string();
656 let mut buf = BytesMut::new();
657 <String as Encoder<BigEndian, 32, true, false>>::encode(&original, &mut buf, 0).unwrap();
658
659 let encoded = buf.freeze();
660
661 println!("Encoded String: {}", hex::encode(&encoded));
662
663 let expected_encoded = "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e48656c6c6f2c20576f726c642121000000000000000000000000000000000000";
664
665 assert_eq!(hex::encode(&encoded), expected_encoded);
666
667 let decoded = <String as Encoder<BigEndian, 32, true, false>>::decode(&encoded, 0).unwrap();
668
669 assert_eq!(original, decoded);
670 }
671 #[test]
672 fn test_string_encoding_fluent() {
673 let original = "Hello, World!!".to_string();
674 let mut buf = BytesMut::new();
675 <String as Encoder<LittleEndian, 4, false, false>>::encode(&original, &mut buf, 0).unwrap();
676
677 let encoded = buf.freeze();
678
679 println!("Encoded String: {}", hex::encode(&encoded));
680
681 let expected_encoded = "080000000e00000048656c6c6f2c20576f726c6421210000";
682
683 assert_eq!(hex::encode(&encoded), expected_encoded);
684
685 let decoded =
686 <String as Encoder<LittleEndian, 4, false, false>>::decode(&encoded, 0).unwrap();
687
688 assert_eq!(original, decoded);
689 }
690
691 #[test]
692 fn test_i128_solidity() {
693 let test_cases = [
695 (
697 I128::try_from(42i32).unwrap(),
698 "000000000000000000000000000000000000000000000000000000000000002a",
699 ),
700 (
702 I128::try_from(-42i32).unwrap(),
703 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6",
704 ),
705 (
707 I128::try_from(0i32).unwrap(),
708 "0000000000000000000000000000000000000000000000000000000000000000",
709 ),
710 (
712 I128::try_from(-1i32).unwrap(),
713 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
714 ),
715 (
717 I128::MAX,
718 "000000000000000000000000000000007fffffffffffffffffffffffffffffff",
719 ),
720 (
722 I128::MIN,
723 "ffffffffffffffffffffffffffffffff80000000000000000000000000000000",
724 ),
725 ];
726
727 for (i, (test_value, expected_hex)) in test_cases.iter().enumerate() {
729 println!(
730 "Testing I128 encoding/decoding for case {}; {}",
731 i, test_value
732 );
733 let mut buf = BytesMut::new();
735 SolidityABI::encode(test_value, &mut buf, 0).unwrap();
736 let encoded = buf.freeze();
737
738 let expected_encoded = hex::decode(expected_hex).unwrap();
740 assert_eq!(
741 encoded.to_vec(),
742 expected_encoded,
743 "Case {}: I128 encoding doesn't match expected value",
744 i
745 );
746
747 let decoded = SolidityABI::<I128>::decode(&encoded, 0).unwrap();
749 assert_eq!(
750 decoded, *test_value,
751 "Case {}: Round-trip encoding/decoding failed",
752 i
753 );
754 }
755 }
756
757 #[test]
758 fn test_i256_solidity() {
759 let test_cases = [
761 (
763 I256::try_from(42i32).unwrap(),
764 "000000000000000000000000000000000000000000000000000000000000002a",
765 ),
766 (
768 I256::try_from(-42i32).unwrap(),
769 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6",
770 ),
771 (
773 I256::try_from(0i32).unwrap(),
774 "0000000000000000000000000000000000000000000000000000000000000000",
775 ),
776 (
778 I256::try_from(1234567890i64).unwrap(),
779 "00000000000000000000000000000000000000000000000000000000499602d2",
780 ),
781 (
783 I256::try_from(-1234567890i64).unwrap(),
784 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffb669fd2e",
785 ),
786 (
788 I256::MAX,
789 "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
790 ),
791 (
793 I256::MIN,
794 "8000000000000000000000000000000000000000000000000000000000000000",
795 ),
796 (
798 I256::MAX - I256::ONE,
799 "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
800 ),
801 (
803 I256::MIN + I256::ONE,
804 "8000000000000000000000000000000000000000000000000000000000000001",
805 ),
806 ];
807
808 for (i, (test_value, expected_hex)) in test_cases.iter().enumerate() {
810 println!(
811 "Testing I256 encoding/decoding for case {}; {}",
812 i, test_value
813 );
814 let mut buf = BytesMut::new();
816 SolidityABI::encode(test_value, &mut buf, 0).unwrap();
817 let encoded = buf.freeze();
818
819 let expected_encoded = hex::decode(expected_hex).unwrap();
821 assert_eq!(
822 encoded.to_vec(),
823 expected_encoded,
824 "Case {}: I256 encoding doesn't match expected value",
825 i
826 );
827
828 let decoded = SolidityABI::<I256>::decode(&encoded, 0).unwrap();
830 assert_eq!(
831 decoded, *test_value,
832 "Case {}: Round-trip encoding/decoding failed",
833 i
834 );
835 }
836 }
837
838 #[test]
839 fn test_i128_compact() {
840 let test_cases = [
843 (
845 I128::try_from(42i32).unwrap(),
846 "2a000000000000000000000000000000",
847 ),
848 (
850 I128::try_from(-42i32).unwrap(),
851 "d6ffffffffffffffffffffffffffffff",
852 ),
853 (
855 I128::try_from(0i32).unwrap(),
856 "00000000000000000000000000000000",
857 ),
858 (
860 I128::try_from(-1i32).unwrap(),
861 "ffffffffffffffffffffffffffffffff",
862 ),
863 (I128::MAX, "ffffffffffffffffffffffffffffff7f"),
865 (I128::MIN, "00000000000000000000000000000080"),
867 ];
868
869 for (i, (test_value, expected_hex)) in test_cases.iter().enumerate() {
871 println!(
872 "Testing I128 CompactABI encoding/decoding for case {}; {}",
873 i, test_value
874 );
875 let mut buf = BytesMut::new();
877 CompactABI::encode(test_value, &mut buf, 0).unwrap();
878 let encoded = buf.freeze();
879
880 let expected_encoded = hex::decode(expected_hex).unwrap();
882 assert_eq!(
883 encoded.to_vec(),
884 expected_encoded,
885 "Case {}: I128 CompactABI encoding doesn't match expected value",
886 i
887 );
888
889 let decoded = CompactABI::<I128>::decode(&encoded, 0).unwrap();
891 assert_eq!(
892 decoded, *test_value,
893 "Case {}: CompactABI round-trip encoding/decoding failed",
894 i
895 );
896 }
897 }
898
899 #[test]
900 fn test_i256_compact() {
901 let test_cases = [
904 (
906 I256::try_from(42i32).unwrap(),
907 "2a00000000000000000000000000000000000000000000000000000000000000",
908 ),
909 (
911 I256::try_from(-42i32).unwrap(),
912 "d6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
913 ),
914 (
916 I256::try_from(0i32).unwrap(),
917 "0000000000000000000000000000000000000000000000000000000000000000",
918 ),
919 (
921 I256::try_from(1234567890i64).unwrap(),
922 "d202964900000000000000000000000000000000000000000000000000000000",
923 ),
924 (
926 I256::try_from(-1234567890i64).unwrap(),
927 "2efd69b6ffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
928 ),
929 (
931 I256::MAX,
932 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
933 ),
934 (
936 I256::MIN,
937 "0000000000000000000000000000000000000000000000000000000000000080",
938 ),
939 ];
940
941 for (i, (test_value, expected_hex)) in test_cases.iter().enumerate() {
943 println!(
944 "Testing I256 CompactABI encoding/decoding for case {}; {}",
945 i, test_value
946 );
947 let mut buf = BytesMut::new();
949 CompactABI::encode(test_value, &mut buf, 0).unwrap();
950 let encoded = buf.freeze();
951
952 let expected_encoded = hex::decode(expected_hex).unwrap();
954 assert_eq!(
955 encoded.to_vec(),
956 expected_encoded,
957 "Case {}: I256 CompactABI encoding doesn't match expected value",
958 i
959 );
960
961 let decoded = CompactABI::<I256>::decode(&encoded, 0).unwrap();
963 assert_eq!(
964 decoded, *test_value,
965 "Case {}: CompactABI round-trip encoding/decoding failed",
966 i
967 );
968 }
969 }
970
971 #[test]
972 fn test_i256_error_conditions() {
973 let too_small_buffer = BytesMut::new().freeze();
975 let result = SolidityABI::<I256>::decode(&too_small_buffer, 0);
976 assert!(result.is_err(), "Decoding from an empty buffer should fail");
977
978 let small_buffer = BytesMut::from(&[0u8; 16][..]).freeze();
980 let result = SolidityABI::<I256>::decode(&small_buffer, 0);
981 assert!(
982 result.is_err(),
983 "Decoding from a buffer smaller than 32 bytes should fail"
984 );
985
986 let buffer = BytesMut::from(&[0u8; 32][..]).freeze();
989 let result = SolidityABI::<I256>::decode(&buffer, 1); assert!(
991 result.is_err(),
992 "Decoding with an offset that would read beyond buffer should fail"
993 );
994
995 let too_small_buffer = BytesMut::new().freeze();
997 let result = CompactABI::<I256>::decode(&too_small_buffer, 0);
998 assert!(
999 result.is_err(),
1000 "CompactABI decoding from an empty buffer should fail"
1001 );
1002 }
1003}