1use arrayvec::ArrayVec;
18
19use crate::{
20 alloc::vec::Vec,
21 codec::{Decode, Encode, EncodeAsRef, Input, Output},
22 encode_like::EncodeLike,
23 DecodeWithMemTracking, Error,
24};
25
26#[cfg(feature = "fuzz")]
27use arbitrary::Arbitrary;
28
29struct ArrayVecWrapper<const N: usize>(ArrayVec<u8, N>);
30
31impl<const N: usize> Output for ArrayVecWrapper<N> {
32 fn write(&mut self, bytes: &[u8]) {
33 let old_len = self.0.len();
34 let new_len = old_len + bytes.len();
35
36 assert!(new_len <= self.0.capacity());
37 unsafe {
38 self.0.set_len(new_len);
39 }
40
41 self.0[old_len..new_len].copy_from_slice(bytes);
42 }
43
44 fn push_byte(&mut self, byte: u8) {
45 self.0.push(byte);
46 }
47}
48
49pub trait CompactLen<T> {
51 fn compact_len(val: &T) -> usize;
53}
54
55#[derive(Eq, PartialEq, Clone, Copy, Ord, PartialOrd)]
57#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
58pub struct Compact<T>(pub T);
59
60impl<T> From<T> for Compact<T> {
61 fn from(x: T) -> Compact<T> {
62 Compact(x)
63 }
64}
65
66impl<'a, T: Copy> From<&'a T> for Compact<T> {
67 fn from(x: &'a T) -> Compact<T> {
68 Compact(*x)
69 }
70}
71
72pub trait CompactAs: From<Compact<Self>> {
74 type As;
76
77 fn encode_as(&self) -> &Self::As;
79
80 fn decode_from(_: Self::As) -> Result<Self, Error>;
82}
83
84impl<T> EncodeLike for Compact<T> where for<'a> CompactRef<'a, T>: Encode {}
85
86impl<T> Encode for Compact<T>
87where
88 for<'a> CompactRef<'a, T>: Encode,
89{
90 fn size_hint(&self) -> usize {
91 CompactRef(&self.0).size_hint()
92 }
93
94 fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
95 CompactRef(&self.0).encode_to(dest)
96 }
97
98 fn encode(&self) -> Vec<u8> {
99 CompactRef(&self.0).encode()
100 }
101
102 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
103 CompactRef(&self.0).using_encoded(f)
104 }
105}
106
107impl<T> EncodeLike for CompactRef<'_, T>
108where
109 T: CompactAs,
110 for<'b> CompactRef<'b, T::As>: Encode,
111{
112}
113
114impl<T> Encode for CompactRef<'_, T>
115where
116 T: CompactAs,
117 for<'b> CompactRef<'b, T::As>: Encode,
118{
119 fn size_hint(&self) -> usize {
120 CompactRef(self.0.encode_as()).size_hint()
121 }
122
123 fn encode_to<Out: Output + ?Sized>(&self, dest: &mut Out) {
124 CompactRef(self.0.encode_as()).encode_to(dest)
125 }
126
127 fn encode(&self) -> Vec<u8> {
128 CompactRef(self.0.encode_as()).encode()
129 }
130
131 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
132 CompactRef(self.0.encode_as()).using_encoded(f)
133 }
134}
135
136impl<T> Decode for Compact<T>
137where
138 T: CompactAs,
139 Compact<T::As>: Decode,
140{
141 fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
142 let as_ = Compact::<T::As>::decode(input)?;
143 Ok(Compact(<T as CompactAs>::decode_from(as_.0)?))
144 }
145}
146
147impl<T> DecodeWithMemTracking for Compact<T>
148where
149 T: CompactAs,
150 Compact<T::As>: DecodeWithMemTracking,
151{
152}
153
154macro_rules! impl_from_compact {
155 ( $( $ty:ty ),* ) => {
156 $(
157 impl From<Compact<$ty>> for $ty {
158 fn from(x: Compact<$ty>) -> $ty { x.0 }
159 }
160 )*
161 }
162}
163
164impl_from_compact! { (), u8, u16, u32, u64, u128 }
165
166#[derive(Eq, PartialEq, Clone, Copy)]
168pub struct CompactRef<'a, T>(pub &'a T);
169
170impl<'a, T> From<&'a T> for CompactRef<'a, T> {
171 fn from(x: &'a T) -> Self {
172 CompactRef(x)
173 }
174}
175
176impl<T> core::fmt::Debug for Compact<T>
177where
178 T: core::fmt::Debug,
179{
180 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
181 self.0.fmt(f)
182 }
183}
184
185#[cfg(feature = "serde")]
186impl<T> serde::Serialize for Compact<T>
187where
188 T: serde::Serialize,
189{
190 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
191 where
192 S: serde::Serializer,
193 {
194 T::serialize(&self.0, serializer)
195 }
196}
197
198#[cfg(feature = "serde")]
199impl<'de, T> serde::Deserialize<'de> for Compact<T>
200where
201 T: serde::Deserialize<'de>,
202{
203 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
204 where
205 D: serde::Deserializer<'de>,
206 {
207 T::deserialize(deserializer).map(Compact)
208 }
209}
210
211pub trait HasCompact: Sized {
213 type Type: for<'a> EncodeAsRef<'a, Self> + Decode + From<Self> + Into<Self>;
215}
216
217impl<'a, T: 'a> EncodeAsRef<'a, T> for Compact<T>
218where
219 CompactRef<'a, T>: Encode + From<&'a T>,
220{
221 type RefType = CompactRef<'a, T>;
222}
223
224impl<T: 'static> HasCompact for T
225where
226 Compact<T>: for<'a> EncodeAsRef<'a, T> + Decode + From<Self> + Into<Self>,
227{
228 type Type = Compact<T>;
229}
230
231impl Encode for CompactRef<'_, ()> {
232 fn encode_to<W: Output + ?Sized>(&self, _dest: &mut W) {}
233
234 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
235 f(&[])
236 }
237
238 fn encode(&self) -> Vec<u8> {
239 Vec::new()
240 }
241}
242
243struct WrappedPrimitive<T>(T);
244
245#[inline(always)]
246fn compact_extra_bytes(x: u64) -> usize {
247 (0..8).find(|&l| x < 1 << (7 * (l + 1))).unwrap_or(8)
248}
249
250impl<T> CompactLen<T> for WrappedPrimitive<T>
251where
252 T: Copy + Into<u64>,
253{
254 fn compact_len(val: &T) -> usize {
255 1 + compact_extra_bytes((*val).into())
256 }
257}
258
259impl<T> Encode for WrappedPrimitive<T>
260where
261 T: Copy + Into<u64>,
262{
263 fn size_hint(&self) -> usize {
264 Self::compact_len(&self.0)
265 }
266
267 fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
268 let x = self.0.into();
269 let l = compact_extra_bytes(x);
270 let prefix = if l == 8 { 0xff } else { !(0xff >> l) | (x >> (8 * l)) as u8 };
271 dest.push_byte(prefix);
272 dest.write(&x.to_le_bytes()[..l]);
273 }
274
275 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
276 let mut r = ArrayVecWrapper(ArrayVec::<u8, 9>::new());
277 self.encode_to(&mut r);
278 f(&r.0)
279 }
280}
281
282impl<T> Decode for WrappedPrimitive<T>
283where
284 T: Copy + TryFrom<u64>,
285{
286 fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
287 let prefix = input.read_byte()?;
288 let l = prefix.leading_ones() as usize;
289 let mut buf = [0u8; 8];
290 input.read(&mut buf[..l])?;
291 let high = if l == 8 { 0 } else { u64::from(prefix & (0x7f >> l)) << (8 * l) };
292 let x = u64::from_le_bytes(buf) | high;
293 if compact_extra_bytes(x) != l {
294 return Err("Non-canonical compact encoding".into());
295 }
296 T::try_from(x).map(Self).map_err(|_| "Out of range".into())
297 }
298}
299
300impl Encode for CompactRef<'_, u8> {
301 fn size_hint(&self) -> usize {
302 WrappedPrimitive(*self.0).size_hint()
303 }
304
305 fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
306 WrappedPrimitive(*self.0).encode_to(dest)
307 }
308
309 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
310 WrappedPrimitive(*self.0).using_encoded(f)
311 }
312}
313
314impl CompactLen<u8> for Compact<u8> {
315 fn compact_len(val: &u8) -> usize {
316 WrappedPrimitive::<u8>::compact_len(val)
317 }
318}
319
320impl Encode for CompactRef<'_, u16> {
321 fn size_hint(&self) -> usize {
322 WrappedPrimitive(*self.0).size_hint()
323 }
324
325 fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
326 WrappedPrimitive(*self.0).encode_to(dest)
327 }
328
329 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
330 WrappedPrimitive(*self.0).using_encoded(f)
331 }
332}
333
334impl CompactLen<u16> for Compact<u16> {
335 fn compact_len(val: &u16) -> usize {
336 WrappedPrimitive::<u16>::compact_len(val)
337 }
338}
339
340impl Encode for CompactRef<'_, u32> {
341 fn size_hint(&self) -> usize {
342 WrappedPrimitive(*self.0).size_hint()
343 }
344
345 fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
346 WrappedPrimitive(*self.0).encode_to(dest)
347 }
348
349 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
350 WrappedPrimitive(*self.0).using_encoded(f)
351 }
352}
353
354impl CompactLen<u32> for Compact<u32> {
355 fn compact_len(val: &u32) -> usize {
356 WrappedPrimitive::<u32>::compact_len(val)
357 }
358}
359
360impl Encode for CompactRef<'_, u64> {
361 fn size_hint(&self) -> usize {
362 WrappedPrimitive(*self.0).size_hint()
363 }
364
365 fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
366 WrappedPrimitive(*self.0).encode_to(dest)
367 }
368
369 fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
370 WrappedPrimitive(*self.0).using_encoded(f)
371 }
372}
373
374impl CompactLen<u64> for Compact<u64> {
375 fn compact_len(val: &u64) -> usize {
376 WrappedPrimitive::<u64>::compact_len(val)
377 }
378}
379
380impl Encode for CompactRef<'_, u128> {
381 fn size_hint(&self) -> usize {
382 Compact::<u128>::compact_len(self.0)
383 }
384
385 fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
386 let l = (*self.0 & u64::MAX as u128) as u64;
387 let h = (*self.0 >> 64) as u64;
388 WrappedPrimitive::<u64>::encode_to(&WrappedPrimitive(l), dest);
389 WrappedPrimitive::<u64>::encode_to(&WrappedPrimitive(h), dest);
390 }
391}
392
393impl CompactLen<u128> for Compact<u128> {
394 fn compact_len(val: &u128) -> usize {
395 let l = (*val & u64::MAX as u128) as u64;
396 let h = (*val >> 64) as u64;
397 Compact::compact_len(&l) + Compact::compact_len(&h)
398 }
399}
400
401impl Decode for Compact<()> {
402 fn decode<I: Input>(_input: &mut I) -> Result<Self, Error> {
403 Ok(Compact(()))
404 }
405}
406
407impl DecodeWithMemTracking for Compact<()> {}
408
409impl Decode for Compact<u8> {
410 fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
411 WrappedPrimitive::<u8>::decode(input).map(|w| Compact(w.0))
412 }
413}
414
415impl DecodeWithMemTracking for Compact<u8> {}
416
417impl Decode for Compact<u16> {
418 fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
419 WrappedPrimitive::<u16>::decode(input).map(|w| Compact(w.0))
420 }
421}
422
423impl DecodeWithMemTracking for Compact<u16> {}
424
425impl Decode for Compact<u32> {
426 fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
427 WrappedPrimitive::<u32>::decode(input).map(|w| Compact(w.0))
428 }
429}
430
431impl DecodeWithMemTracking for Compact<u32> {}
432
433impl Decode for Compact<u64> {
434 fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
435 WrappedPrimitive::<u64>::decode(input).map(|w| Compact(w.0))
436 }
437}
438
439impl DecodeWithMemTracking for Compact<u64> {}
440
441impl Decode for Compact<u128> {
442 fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
443 let l = WrappedPrimitive::<u64>::decode(input).map(|w| Compact(w.0))?.0;
444 let h = WrappedPrimitive::<u64>::decode(input).map(|w| Compact(w.0))?.0;
445 Ok(Compact((h as u128) << 64 | l as u128))
446 }
447}
448
449impl DecodeWithMemTracking for Compact<u128> {}
450
451#[cfg(test)]
452mod tests {
453 use super::*;
454
455 #[test]
456 fn compact_128_encoding_works() {
457 let tests = [
458 (0u128, 2),
459 (63, 2),
460 (64, 2),
461 (16383, 3),
462 (16384, 4),
463 (1073741823, 6),
464 (1073741824, 6),
465 ((1 << 32) - 1, 6),
466 (1 << 32, 6),
467 (1 << 40, 7), (1 << 48, 8),
469 ((1 << 56) - 1, 9),
470 (1 << 56, 10),
471 ((1 << 64) - 1, 10),
472 (1 << 64, 2),
473 (1 << 72, 3),
474 (1 << 80, 4),
475 (1 << 88, 5),
476 (1 << 96, 6),
477 (1 << 104, 7), (1 << 112, 8),
479 ((1 << 120) - 1, 17),
480 (1 << 120, 10),
481 (u128::MAX, 18),
482 ];
483 for &(n, l) in &tests {
484 let encoded = Compact(n).encode();
485 println!("{}", hex::encode(&encoded));
486 assert_eq!(encoded.len(), l);
487 assert_eq!(Compact::compact_len(&n), l);
488 assert_eq!(<Compact<u128>>::decode(&mut &encoded[..]).unwrap().0, n);
489 }
490 }
491
492 #[test]
493 fn compact_64_encoding_works() {
494 let tests = [
495 (0u64, 1usize),
496 (63, 1),
497 (64, 1),
498 (16383, 2),
499 (16384, 3),
500 (1073741823, 5),
501 (1073741824, 5),
502 ((1 << 32) - 1, 5),
503 (1 << 32, 5),
504 (1 << 40, 6),
505 (1 << 48, 7),
506 ((1 << 56) - 1, 8),
507 (1 << 56, 9),
508 (u64::MAX, 9),
509 ];
510 for &(n, l) in &tests {
511 let encoded = Compact(n).encode();
512 assert_eq!(encoded.len(), l);
513 assert_eq!(Compact::compact_len(&n), l);
514 assert_eq!(<Compact<u64>>::decode(&mut &encoded[..]).unwrap().0, n);
515 }
516 }
517
518 #[test]
519 fn compact_32_encoding_works() {
520 let tests = [
521 (0u32, 1usize),
522 (63, 1),
523 (64, 1),
524 (16383, 2),
525 (16384, 3),
526 (1073741823, 5),
527 (1073741824, 5),
528 (u32::MAX, 5),
529 ];
530 for &(n, l) in &tests {
531 let encoded = Compact(n).encode();
532 assert_eq!(encoded.len(), l);
533 assert_eq!(Compact::compact_len(&n), l);
534 assert_eq!(<Compact<u32>>::decode(&mut &encoded[..]).unwrap().0, n);
535 }
536 }
537
538 #[test]
539 fn compact_16_encoding_works() {
540 let tests = [(0u16, 1usize), (63, 1), (64, 1), (16383, 2), (16384, 3), (65535, 3)];
541 for &(n, l) in &tests {
542 let encoded = Compact(n).encode();
543 assert_eq!(encoded.len(), l);
544 assert_eq!(Compact::compact_len(&n), l);
545 assert_eq!(<Compact<u16>>::decode(&mut &encoded[..]).unwrap().0, n);
546 }
547 assert!(<Compact<u16>>::decode(&mut &Compact(65536u32).encode()[..]).is_err());
548 }
549
550 #[test]
551 fn compact_8_encoding_works() {
552 let tests = [(0u8, 1usize), (63, 1), (64, 1), (255, 2)];
553 for &(n, l) in &tests {
554 let encoded = Compact(n).encode();
555 assert_eq!(encoded.len(), l);
556 assert_eq!(Compact::compact_len(&n), l);
557 assert_eq!(<Compact<u8>>::decode(&mut &encoded[..]).unwrap().0, n);
558 }
559 assert!(<Compact<u8>>::decode(&mut &Compact(256u32).encode()[..]).is_err());
560 }
561
562 fn hexify(bytes: &[u8]) -> String {
563 bytes
564 .iter()
565 .map(|ref b| format!("{:02x}", b))
566 .collect::<Vec<String>>()
567 .join(" ")
568 }
569
570 #[test]
571 fn compact_integers_encoded_as_expected() {
572 let tests = [
573 (0u64, "00"),
574 (63, "3f"),
575 (64, "40"),
576 (16383, "bf ff"),
577 (16384, "c0 00 40"),
578 (1073741823, "f0 ff ff ff 3f"),
579 (1073741824, "f0 00 00 00 40"),
580 ((1 << 32) - 1, "f0 ff ff ff ff"),
581 (1 << 32, "f1 00 00 00 00"),
582 (1 << 40, "f9 00 00 00 00 00"),
583 (1 << 48, "fd 00 00 00 00 00 00"),
584 ((1 << 56) - 1, "fe ff ff ff ff ff ff ff"),
585 (1 << 56, "ff 00 00 00 00 00 00 00 01"),
586 (u64::MAX, "ff ff ff ff ff ff ff ff ff"),
587 ];
588 for &(n, s) in &tests {
589 let encoded = Compact(n).encode();
591 assert_eq!(hexify(&encoded), s);
592 assert_eq!(<Compact<u64>>::decode(&mut &encoded[..]).unwrap().0, n);
593
594 if n <= u32::MAX as u64 {
596 assert_eq!(<Compact<u32>>::decode(&mut &encoded[..]).unwrap().0, n as u32);
597 let encoded = Compact(n as u32).encode();
598 assert_eq!(hexify(&encoded), s);
599 assert_eq!(<Compact<u64>>::decode(&mut &encoded[..]).unwrap().0, n);
600 }
601 if n <= u16::MAX as u64 {
602 assert_eq!(<Compact<u16>>::decode(&mut &encoded[..]).unwrap().0, n as u16);
603 let encoded = Compact(n as u16).encode();
604 assert_eq!(hexify(&encoded), s);
605 assert_eq!(<Compact<u64>>::decode(&mut &encoded[..]).unwrap().0, n);
606 }
607 if n <= u8::MAX as u64 {
608 assert_eq!(<Compact<u8>>::decode(&mut &encoded[..]).unwrap().0, n as u8);
609 let encoded = Compact(n as u8).encode();
610 assert_eq!(hexify(&encoded), s);
611 assert_eq!(<Compact<u64>>::decode(&mut &encoded[..]).unwrap().0, n);
612 }
613 }
614 }
615
616 #[test]
619 fn compact_decode_rejects_non_canonical_encodings() {
620 for extra_bytes in 1..=8 {
621 let prefix = u8::MAX << (8 - extra_bytes);
622 let encode_with_length = |value: u64| {
623 let mut bytes = vec![prefix];
624 bytes.extend_from_slice(&value.to_le_bytes()[..extra_bytes]);
625 bytes
626 };
627 let smallest_value = 1u64 << (7 * extra_bytes);
628 for value in [0, smallest_value - 1] {
629 assert!(<Compact<u64>>::decode(&mut &encode_with_length(value)[..]).is_err());
630 }
631 let canonical = encode_with_length(smallest_value);
632 assert_eq!(canonical, Compact(smallest_value).encode());
633 assert_eq!(<Compact<u64>>::decode(&mut &canonical[..]).unwrap().0, smallest_value);
634 }
635 assert!(<Vec<u8>>::decode(&mut &[0x80, 0x00][..]).is_err());
636 }
637
638 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
639 #[derive(PartialEq, Eq, Clone)]
640 struct Wrapper(u8);
641
642 impl CompactAs for Wrapper {
643 type As = u8;
644 fn encode_as(&self) -> &u8 {
645 &self.0
646 }
647 fn decode_from(x: u8) -> Result<Wrapper, Error> {
648 Ok(Wrapper(x))
649 }
650 }
651
652 impl From<Compact<Wrapper>> for Wrapper {
653 fn from(x: Compact<Wrapper>) -> Wrapper {
654 x.0
655 }
656 }
657
658 #[test]
659 fn compact_as_8_encoding_works() {
660 let tests = [(0u8, 1usize), (63, 1), (64, 1), (255, 2)];
661 for &(n, l) in &tests {
662 let compact: Compact<Wrapper> = Wrapper(n).into();
663 let encoded = compact.encode();
664 assert_eq!(encoded.len(), l);
665 assert_eq!(Compact::compact_len(&n), l);
666 let decoded = <Compact<Wrapper>>::decode(&mut &encoded[..]).unwrap();
667 let wrapper: Wrapper = decoded.into();
668 assert_eq!(wrapper, Wrapper(n));
669 }
670 }
671
672 struct WithCompact<T: HasCompact> {
673 _data: T,
674 }
675
676 #[test]
677 fn compact_as_has_compact() {
678 let _data = WithCompact { _data: Wrapper(1) };
679 }
680
681 #[test]
682 fn compact_using_encoded_arrayvec_size() {
683 Compact(u8::MAX).using_encoded(|_| {});
684 Compact(u16::MAX).using_encoded(|_| {});
685 Compact(u32::MAX).using_encoded(|_| {});
686 Compact(u64::MAX).using_encoded(|_| {});
687 Compact(u128::MAX).using_encoded(|_| {});
688
689 CompactRef(&u8::MAX).using_encoded(|_| {});
690 CompactRef(&u16::MAX).using_encoded(|_| {});
691 CompactRef(&u32::MAX).using_encoded(|_| {});
692 CompactRef(&u64::MAX).using_encoded(|_| {});
693 CompactRef(&u128::MAX).using_encoded(|_| {});
694 }
695
696 #[test]
697 #[should_panic]
698 fn array_vec_output_oob() {
699 let mut v = ArrayVecWrapper(ArrayVec::<u8, 4>::new());
700 v.write(&[1, 2, 3, 4, 5]);
701 }
702
703 #[test]
704 fn array_vec_output() {
705 let mut v = ArrayVecWrapper(ArrayVec::<u8, 4>::new());
706 v.write(&[1, 2, 3, 4]);
707 }
708
709 #[test]
710 fn compact_u64_test() {
711 for a in [
712 u64::MAX,
713 u64::MAX - 1,
714 u64::MAX << 8,
715 (u64::MAX << 8) - 1,
716 u64::MAX << 16,
717 (u64::MAX << 16) - 1,
718 ]
719 .iter()
720 {
721 let e = Compact::<u64>::encode(&Compact(*a));
722 let d = Compact::<u64>::decode(&mut &e[..]).unwrap().0;
723 assert_eq!(*a, d);
724 }
725 }
726
727 #[test]
728 fn compact_u128_test() {
729 for a in [u64::MAX as u128, (u64::MAX - 10) as u128, u128::MAX, u128::MAX - 10].iter() {
730 let e = Compact::<u128>::encode(&Compact(*a));
731 let d = Compact::<u128>::decode(&mut &e[..]).unwrap().0;
732 assert_eq!(*a, d);
733 }
734 }
735
736 macro_rules! quick_check_roundtrip {
737 ( $( $ty:ty : $test:ident ),* ) => {
738 $(
739 quickcheck::quickcheck! {
740 fn $test(v: $ty) -> bool {
741 let encoded = Compact(v).encode();
742 let deencoded = <Compact<$ty>>::decode(&mut &encoded[..]).unwrap().0;
743
744 v == deencoded
745 }
746 }
747 )*
748 }
749 }
750
751 quick_check_roundtrip! {
752 u8: u8_roundtrip,
753 u16: u16_roundtrip,
754 u32 : u32_roundtrip,
755 u64 : u64_roundtrip,
756 u128 : u128_roundtrip
757 }
758}