1use crate::{
2 bytes_codec::{read_bytes_header, write_bytes, write_bytes_solidity, write_bytes_wasm},
3 encoder::{align_up, read_u32_aligned, write_u32_aligned, Encoder},
4 error::{CodecError, DecodingError},
5};
6use alloc::{format, string::ToString, vec::Vec};
7use byteorder::ByteOrder;
8use bytes::{Buf, BytesMut};
9use core::{fmt::Debug, hash::Hash};
10use hashbrown::{HashMap, HashSet};
11
12impl<K, V, B: ByteOrder, const ALIGN: usize> Encoder<B, ALIGN, false, false> for HashMap<K, V>
14where
15 K: Default + Sized + Encoder<B, ALIGN, false, false> + Eq + Hash + Ord,
16 V: Default + Sized + Encoder<B, ALIGN, false, false>,
17{
18 const HEADER_SIZE: usize = 4 + 8 + 8; const IS_DYNAMIC: bool = true;
20
21 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
22 let aligned_header_el_size = align_up::<ALIGN>(4);
23 let aligned_header_size = align_up::<ALIGN>(Self::HEADER_SIZE);
24
25 if buf.len() < offset + aligned_header_size {
27 buf.resize(offset + aligned_header_size, 0);
28 }
29
30 write_u32_aligned::<B, ALIGN>(buf, offset, self.len() as u32);
32
33 let mut entries: Vec<_> = self.iter().collect();
35 entries.sort_by(|a, b| a.0.cmp(b.0));
36
37 let mut key_buf = BytesMut::zeroed(align_up::<ALIGN>(K::HEADER_SIZE) * self.len());
39
40 for (i, (key, _)) in entries.iter().enumerate() {
41 let key_offset = align_up::<ALIGN>(K::HEADER_SIZE) * i;
42 key.encode(&mut key_buf, key_offset)?;
43 }
44
45 write_bytes::<B, ALIGN, false>(
47 buf,
48 offset + aligned_header_el_size,
49 &key_buf,
50 entries.len() as u32,
51 );
52
53 let mut value_buf = BytesMut::zeroed(align_up::<ALIGN>(V::HEADER_SIZE) * self.len());
55 for (i, (_, value)) in entries.iter().enumerate() {
56 let value_offset = align_up::<ALIGN>(V::HEADER_SIZE) * i;
57 value.encode(&mut value_buf, value_offset)?;
58 }
59
60 write_bytes_wasm::<B, ALIGN>(buf, offset + aligned_header_el_size * 3, &value_buf);
61
62 Ok(())
63 }
64
65 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
66 let aligned_header_el_size = align_up::<ALIGN>(4);
67 let aligned_header_size = align_up::<ALIGN>(Self::HEADER_SIZE);
68
69 if buf.remaining() < offset + aligned_header_size {
70 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
71 expected: offset + aligned_header_size,
72 found: buf.remaining(),
73 msg: "Not enough data to decode HashMap header".to_string(),
74 }));
75 }
76
77 let length = read_u32_aligned::<B, ALIGN>(buf, offset)? as usize;
78
79 let (keys_offset, keys_length) =
80 read_bytes_header::<B, ALIGN, false>(buf, offset + aligned_header_el_size)?;
81
82 let (values_offset, values_length) =
83 read_bytes_header::<B, ALIGN, false>(buf, offset + aligned_header_el_size * 3)?;
84
85 let key_bytes = &buf.chunk()[keys_offset..keys_offset + keys_length];
86 let value_bytes = &buf.chunk()[values_offset..values_offset + values_length];
87
88 let keys = (0..length).map(|i| {
89 let key_offset = align_up::<ALIGN>(K::HEADER_SIZE) * i;
90 K::decode(&key_bytes, key_offset).unwrap_or_default()
91 });
92
93 let values = (0..length).map(|i| {
94 let value_offset = align_up::<ALIGN>(V::HEADER_SIZE) * i;
95 V::decode(&value_bytes, value_offset).unwrap_or_default()
96 });
97
98 let result: HashMap<K, V> = keys.zip(values).collect();
99
100 if result.len() != length {
101 return Err(CodecError::Decoding(DecodingError::InvalidData(format!(
102 "Expected {} elements, but decoded {}",
103 length,
104 result.len()
105 ))));
106 }
107
108 Ok(result)
109 }
110
111 fn partial_decode(buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
112 let aligned_header_size = align_up::<ALIGN>(Self::HEADER_SIZE);
113
114 if buf.remaining() < offset + aligned_header_size {
115 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
116 expected: offset + aligned_header_size,
117 found: buf.remaining(),
118 msg: "Not enough data to decode HashMap header".to_string(),
119 }));
120 }
121
122 let (keys_offset, keys_length) =
123 read_bytes_header::<B, ALIGN, false>(buf, offset + align_up::<ALIGN>(4))?;
124 let (_values_offset, values_length) =
125 read_bytes_header::<B, ALIGN, false>(buf, offset + align_up::<ALIGN>(12))?;
126
127 Ok((keys_offset, keys_length + values_length))
128 }
129}
130impl<K, V, B: ByteOrder, const ALIGN: usize> Encoder<B, ALIGN, true, false> for HashMap<K, V>
132where
133 K: Debug + Default + Sized + Encoder<B, ALIGN, true, false> + Eq + Hash + Ord,
134 V: Debug + Default + Sized + Encoder<B, ALIGN, true, false>,
135{
136 const HEADER_SIZE: usize = 32 + 32 + 32 + 32; const IS_DYNAMIC: bool = true;
139
140 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
141 if buf.len() < offset + Self::HEADER_SIZE {
143 buf.resize(offset + Self::HEADER_SIZE, 0);
144 }
145
146 write_u32_aligned::<B, ALIGN>(buf, offset, 32_u32);
148
149 write_u32_aligned::<B, ALIGN>(buf, offset + 32, self.len() as u32);
151
152 let mut entries: Vec<_> = self.iter().collect();
154 entries.sort_by(|a, b| a.0.cmp(b.0));
155
156 let mut key_buf = BytesMut::zeroed(align_up::<ALIGN>(K::HEADER_SIZE) * self.len());
158
159 for (i, (key, _)) in entries.iter().enumerate() {
160 let key_offset = align_up::<ALIGN>(K::HEADER_SIZE) * i;
161 key.encode(&mut key_buf, key_offset)?;
162 }
163 let relative_key_offset = buf.len() - offset - 64;
164 write_u32_aligned::<B, ALIGN>(buf, offset + 64, relative_key_offset as u32);
166
167 write_bytes_solidity::<B, ALIGN>(buf, offset + 64, &key_buf, entries.len() as u32);
169
170 let relative_value_offset = buf.len() - offset - 96;
172 write_u32_aligned::<B, ALIGN>(buf, offset + 96, relative_value_offset as u32);
173
174 let mut value_buf = BytesMut::zeroed(align_up::<ALIGN>(V::HEADER_SIZE) * self.len());
176 for (i, (_, value)) in entries.iter().enumerate() {
177 let value_offset = align_up::<ALIGN>(V::HEADER_SIZE) * i;
178 value.encode(&mut value_buf, value_offset)?;
179 }
180
181 write_bytes_solidity::<B, ALIGN>(buf, buf.len(), &value_buf, entries.len() as u32);
182
183 Ok(())
184 }
185
186 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
188 const KEYS_OFFSET: usize = 32;
189 const VALUES_OFFSET: usize = 64;
190
191 let header_end = offset
193 .checked_add(Self::HEADER_SIZE)
194 .ok_or(CodecError::Decoding(DecodingError::Overflow))?;
195
196 if buf.remaining() < header_end {
197 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
198 expected: header_end,
199 found: buf.remaining(),
200 msg: "Not enough data to decode HashMap header".to_string(),
201 }));
202 }
203
204 let data_offset = read_u32_aligned::<B, ALIGN>(buf, offset)? as usize;
206
207 let start_offset = offset
209 .checked_add(data_offset)
210 .ok_or(CodecError::Decoding(DecodingError::Overflow))?;
211
212 let length = read_u32_aligned::<B, ALIGN>(buf, start_offset)? as usize;
214 if length == 0 {
215 return Ok(HashMap::new());
216 }
217
218 let keys_offset = read_u32_aligned::<B, ALIGN>(buf, start_offset + KEYS_OFFSET)? as usize;
220 let values_offset =
221 read_u32_aligned::<B, ALIGN>(buf, start_offset + VALUES_OFFSET)? as usize;
222
223 let keys_start = keys_offset
225 .checked_add(start_offset)
226 .and_then(|sum| sum.checked_add(KEYS_OFFSET))
227 .ok_or(CodecError::Decoding(DecodingError::Overflow))?;
228 let values_start = values_offset
229 .checked_add(start_offset)
230 .and_then(|sum| sum.checked_add(VALUES_OFFSET))
231 .ok_or(CodecError::Decoding(DecodingError::Overflow))?;
232
233 let mut result = HashMap::with_capacity(length);
234
235 let keys_data = &buf.chunk()[keys_start + 32..];
236 let values_data = &buf.chunk()[values_start + 32..];
237
238 for i in 0..length {
239 let key_offset = align_up::<ALIGN>(K::HEADER_SIZE)
240 .checked_mul(i)
241 .ok_or(CodecError::Decoding(DecodingError::Overflow))?;
242 let value_offset = align_up::<ALIGN>(V::HEADER_SIZE)
243 .checked_mul(i)
244 .ok_or(CodecError::Decoding(DecodingError::Overflow))?;
245
246 let key = K::decode(&keys_data, key_offset)?;
247 let value = V::decode(&values_data, value_offset)?;
248
249 result.insert(key, value);
250 }
251
252 Ok(result)
253 }
254
255 fn partial_decode(buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
256 let aligned_header_size = align_up::<ALIGN>(Self::HEADER_SIZE);
257
258 if buf.remaining() < offset + aligned_header_size {
259 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
260 expected: offset + aligned_header_size,
261 found: buf.remaining(),
262 msg: "Not enough data to decode HashMap header".to_string(),
263 }));
264 }
265
266 let (keys_offset, keys_length) =
267 read_bytes_header::<B, ALIGN, false>(buf, offset + align_up::<ALIGN>(4))?;
268 let (_values_offset, values_length) =
269 read_bytes_header::<B, ALIGN, false>(buf, offset + align_up::<ALIGN>(12))?;
270
271 Ok((keys_offset, keys_length + values_length))
272 }
273}
274
275impl<T, B: ByteOrder, const ALIGN: usize> Encoder<B, ALIGN, false, false> for HashSet<T>
277where
278 T: Default + Sized + Encoder<B, ALIGN, false, false> + Eq + Hash + Ord,
279{
280 const HEADER_SIZE: usize = 4 + 8; const IS_DYNAMIC: bool = true;
282
283 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
284 let aligned_offset = align_up::<ALIGN>(offset);
285 let aligned_header_el_size = align_up::<ALIGN>(4);
286 let aligned_header_size = align_up::<ALIGN>(Self::HEADER_SIZE);
287
288 if buf.len() < aligned_offset + aligned_header_size {
290 buf.resize(aligned_offset + aligned_header_size, 0);
291 }
292
293 write_u32_aligned::<B, ALIGN>(buf, aligned_offset, self.len() as u32);
295
296 let mut entries: Vec<_> = self.iter().collect();
298 entries.sort();
299
300 let mut value_buf = BytesMut::zeroed(align_up::<ALIGN>(T::HEADER_SIZE) * self.len());
302 for (i, value) in entries.iter().enumerate() {
303 let value_offset = align_up::<ALIGN>(T::HEADER_SIZE) * i;
304 value.encode(&mut value_buf, value_offset)?;
305 }
306
307 write_bytes::<B, ALIGN, false>(
309 buf,
310 aligned_offset + aligned_header_el_size,
311 &value_buf,
312 entries.len() as u32,
313 );
314
315 Ok(())
316 }
317
318 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
319 let aligned_offset = align_up::<ALIGN>(offset);
320 let aligned_header_size = align_up::<ALIGN>(Self::HEADER_SIZE);
321
322 if buf.remaining() < aligned_offset + aligned_header_size {
323 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
324 expected: aligned_offset + aligned_header_size,
325 found: buf.remaining(),
326 msg: "Not enough data to decode HashSet header".to_string(),
327 }));
328 }
329
330 let length = read_u32_aligned::<B, ALIGN>(buf, aligned_offset)? as usize;
331
332 let (data_offset, data_length) =
333 read_bytes_header::<B, ALIGN, false>(buf, aligned_offset + align_up::<ALIGN>(4))?;
334
335 let mut result = HashSet::with_capacity(length);
336
337 let value_bytes = &buf.chunk()[data_offset..data_offset + data_length];
338
339 for i in 0..length {
340 let value_offset = align_up::<ALIGN>(T::HEADER_SIZE) * i;
341 let value = T::decode(&value_bytes, value_offset)?;
342 result.insert(value);
343 }
344
345 if result.len() != length {
346 return Err(CodecError::Decoding(DecodingError::InvalidData(format!(
347 "Expected {} elements, but decoded {}",
348 length,
349 result.len()
350 ))));
351 }
352
353 Ok(result)
354 }
355
356 fn partial_decode(buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
357 let aligned_offset = align_up::<ALIGN>(offset);
358 let aligned_header_size = align_up::<ALIGN>(Self::HEADER_SIZE);
359
360 if buf.remaining() < aligned_offset + aligned_header_size {
361 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
362 expected: aligned_offset + aligned_header_size,
363 found: buf.remaining(),
364 msg: "Not enough data to decode HashSet header".to_string(),
365 }));
366 }
367
368 let (data_offset, data_length) =
369 read_bytes_header::<B, ALIGN, false>(buf, aligned_offset + align_up::<ALIGN>(4))?;
370
371 Ok((data_offset, data_length))
372 }
373}
374
375impl<T, B: ByteOrder, const ALIGN: usize> Encoder<B, ALIGN, true, false> for HashSet<T>
377where
378 T: Debug + Default + Sized + Encoder<B, ALIGN, true, false> + Eq + Hash + Ord,
379{
380 const HEADER_SIZE: usize = 32 + 32 + 32; const IS_DYNAMIC: bool = true;
382 fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
383 let aligned_offset = align_up::<ALIGN>(offset);
384
385 if buf.len() < aligned_offset + Self::HEADER_SIZE {
387 buf.resize(aligned_offset + Self::HEADER_SIZE, 0);
388 }
389
390 write_u32_aligned::<B, ALIGN>(buf, aligned_offset, 32_u32);
392
393 write_u32_aligned::<B, ALIGN>(buf, aligned_offset + 32, self.len() as u32);
395
396 let mut entries: Vec<_> = self.iter().collect();
398 entries.sort();
399
400 let mut value_buf = BytesMut::zeroed(align_up::<ALIGN>(T::HEADER_SIZE) * self.len());
402 for (i, value) in entries.iter().enumerate() {
403 let value_offset = align_up::<ALIGN>(T::HEADER_SIZE) * i;
404 value.encode(&mut value_buf, value_offset)?;
405 }
406
407 let relative_data_offset = buf.len() - aligned_offset - 64;
409 write_u32_aligned::<B, ALIGN>(buf, aligned_offset + 64, relative_data_offset as u32);
410
411 write_bytes_solidity::<B, ALIGN>(buf, buf.len(), &value_buf, entries.len() as u32);
413
414 Ok(())
415 }
416
417 fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
418 const DATA_OFFSET: usize = 32;
419
420 let aligned_offset = align_up::<ALIGN>(offset);
421
422 let header_end = aligned_offset
424 .checked_add(Self::HEADER_SIZE)
425 .ok_or(CodecError::Decoding(DecodingError::Overflow))?;
426
427 if buf.remaining() < header_end {
428 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
429 expected: header_end,
430 found: buf.remaining(),
431 msg: "Not enough data to decode HashSet header".to_string(),
432 }));
433 }
434
435 let data_offset = read_u32_aligned::<B, ALIGN>(buf, aligned_offset)? as usize;
437
438 let start_offset = aligned_offset
440 .checked_add(data_offset)
441 .ok_or(CodecError::Decoding(DecodingError::Overflow))?;
442
443 let length = read_u32_aligned::<B, ALIGN>(buf, start_offset)? as usize;
445 if length == 0 {
446 return Ok(HashSet::new());
447 }
448
449 let values_offset = read_u32_aligned::<B, ALIGN>(buf, start_offset + DATA_OFFSET)? as usize;
451
452 let values_start = values_offset
454 .checked_add(start_offset)
455 .and_then(|sum| sum.checked_add(DATA_OFFSET))
456 .ok_or(CodecError::Decoding(DecodingError::Overflow))?;
457
458 let mut result = HashSet::with_capacity(length);
459
460 let values_data = &buf.chunk()[values_start + 32..];
461
462 for i in 0..length {
463 let value_offset = align_up::<ALIGN>(T::HEADER_SIZE)
464 .checked_mul(i)
465 .ok_or(CodecError::Decoding(DecodingError::Overflow))?;
466
467 let value = T::decode(&values_data, value_offset)?;
468 result.insert(value);
469 }
470
471 Ok(result)
472 }
473
474 fn partial_decode(buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
475 let aligned_offset = align_up::<ALIGN>(offset);
476 let aligned_header_size = align_up::<ALIGN>(Self::HEADER_SIZE);
477
478 if buf.remaining() < aligned_offset + aligned_header_size {
479 return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
480 expected: aligned_offset + aligned_header_size,
481 found: buf.remaining(),
482 msg: "Not enough data to decode HashSet header".to_string(),
483 }));
484 }
485
486 let data_offset = read_u32_aligned::<B, ALIGN>(buf, aligned_offset)? as usize;
487 let start_offset = aligned_offset + data_offset;
488 let length = read_u32_aligned::<B, ALIGN>(buf, start_offset)? as usize;
489 let values_offset = read_u32_aligned::<B, ALIGN>(buf, start_offset + 64)? as usize;
490 let values_start = start_offset + 64 + values_offset;
491
492 let data_length = length * align_up::<ALIGN>(T::HEADER_SIZE);
493
494 Ok((values_start + 32, data_length))
495 }
496}
497
498#[cfg(test)]
499mod tests {
500 use super::*;
501 use crate::{
502 encoder::{CompactABI, SolidityABI},
503 test_utils::print_bytes,
504 };
505 use alloc::vec::Vec;
506 use byteorder::BE;
507 use bytes::BytesMut;
508 use hashbrown::HashMap;
509
510 #[test]
511 fn test_nested_map() {
512 let mut values = HashMap::new();
513 values.insert(100, HashMap::from([(1, 2), (3, 4)]));
514 values.insert(3, HashMap::new());
515 values.insert(1000, HashMap::from([(7, 8), (9, 4)]));
516
517 let mut buf = BytesMut::new();
518 CompactABI::encode(&values, &mut buf, 0).unwrap();
519
520 let encoded = buf.freeze();
521 let expected_encoded = "03000000140000000c000000200000005c0000000300000064000000e8030000000000003c000000000000003c00000000000000020000003c000000080000004400000008000000020000004c0000000800000054000000080000000100000003000000020000000400000007000000090000000800000004000000";
522
523 assert_eq!(hex::encode(&encoded), expected_encoded, "Encoding mismatch");
524
525 let decoded = CompactABI::<HashMap<i32, HashMap<i32, i32>>>::decode(&encoded, 0).unwrap();
526 assert_eq!(values, decoded);
527
528 let header =
529 CompactABI::<HashMap<i32, HashMap<i32, i32>>>::partial_decode(&encoded, 0).unwrap();
530
531 assert_eq!(header, (20, 104));
532 println!("Header: {:?}", header);
533 }
534
535 #[test]
536 fn test_vector_of_maps() {
537 let values = vec![
538 HashMap::from([(1, 2), (3, 4)]),
539 HashMap::new(),
540 HashMap::from([(7, 8), (9, 4)]),
541 ];
542
543 let mut buf = BytesMut::new();
544 CompactABI::encode(&values, &mut buf, 0).unwrap();
545
546 let result = buf.freeze();
547 println!("{}", hex::encode(&result));
548
549 let expected_encoded = "030000000c0000005c000000020000003c000000080000004400000008000000000000004c000000000000004c00000000000000020000004c0000000800000054000000080000000100000003000000020000000400000007000000090000000800000004000000";
550
551 assert_eq!(hex::encode(&result), expected_encoded, "Encoding mismatch");
552 let bytes = result.clone();
553 let values2 = CompactABI::<Vec<HashMap<u32, u32>>>::decode(&bytes, 0).unwrap();
554 assert_eq!(values, values2);
555 }
556
557 #[test]
558 fn test_map_of_vectors() {
559 let mut values = HashMap::new();
560 values.insert(vec![0, 1, 2], vec![3, 4, 5]);
561 values.insert(vec![3, 1, 2], vec![3, 4, 5]);
562 values.insert(vec![0, 1, 6], vec![3, 4, 5]);
563 let mut buf = BytesMut::new();
564
565 CompactABI::encode(&values, &mut buf, 0).unwrap();
566 let encoded = buf.freeze();
567
568 let expected_encoded = "0300000014000000480000005c0000004800000003000000240000000c00000003000000300000000c000000030000003c0000000c00000000000000010000000200000000000000010000000600000003000000010000000200000003000000240000000c00000003000000300000000c000000030000003c0000000c000000030000000400000005000000030000000400000005000000030000000400000005000000";
571 assert_eq!(hex::encode(&encoded), expected_encoded, "Encoding mismatch");
572
573 let values2 = CompactABI::<HashMap<Vec<i32>, Vec<i32>>>::decode(&encoded, 0).unwrap();
574 assert_eq!(values, values2);
575 }
576
577 #[test]
578 fn test_set() {
579 let values = HashSet::from([1, 2, 3]);
580 let mut buf = BytesMut::new();
581
582 CompactABI::encode(&values, &mut buf, 0).unwrap();
583 let encoded = buf.freeze();
584
585 println!("{}", hex::encode(&encoded));
586 let expected_encoded = "030000000c0000000c000000010000000200000003000000";
587 assert_eq!(hex::encode(&encoded), expected_encoded, "Encoding mismatch");
588
589 let values2 = CompactABI::<HashSet<i32>>::decode(&encoded, 0).unwrap();
590 assert_eq!(values, values2);
591 }
592
593 #[test]
594 fn test_set_is_sorted() {
595 let values1 = HashSet::from([1, 2, 3, 4, 5, 6, 7, 8, 9]);
596 let mut buf1 = BytesMut::new();
597
598 CompactABI::encode(&values1, &mut buf1, 0).unwrap();
599
600 let values2 = HashSet::from([8, 3, 2, 4, 5, 9, 7, 1, 6]);
601 let mut buf2 = BytesMut::new();
602
603 CompactABI::encode(&values2, &mut buf2, 0).unwrap();
604
605 assert_eq!(&buf1.chunk(), &buf2.chunk());
606 }
607
608 #[test]
609 fn test_set_solidity() {
610 let values = HashSet::from([1, 2, 3]);
611 let mut buf = BytesMut::new();
612 SolidityABI::encode(&values, &mut buf, 0).unwrap();
613 let encoded = buf.freeze();
614 print_bytes::<BE, 32>(&encoded);
615
616 let values2 = SolidityABI::<HashSet<i32>>::decode(&encoded, 0).unwrap();
617 println!("values2: {:?}", values2);
618 assert_eq!(values, values2, "Decoding mismatch for Solidity");
619 }
620
621 #[test]
622 fn test_set_solidity_is_sorted() {
623 let values1 = HashSet::from([1, 2, 3, 4, 5, 6, 7, 8, 9]);
624 let mut buf1 = BytesMut::new();
625
626 SolidityABI::encode(&values1, &mut buf1, 0).unwrap();
627
628 let values2 = HashSet::from([8, 3, 2, 4, 5, 9, 7, 1, 6]);
629 let mut buf2 = BytesMut::new();
630
631 SolidityABI::encode(&values2, &mut buf2, 0).unwrap();
632
633 assert_eq!(
634 &buf1.chunk(),
635 &buf2.chunk(),
636 "Solidity encoding is not sorted"
637 );
638 }
639}