jam_codec/
compact.rs

1// Copyright 2019 Parity Technologies
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! [Compact encoding](https://docs.substrate.io/v3/advanced/scale-codec/#compactgeneral-integers)
16
17use 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
49/// Something that can return the compact encoded length for a given value.
50pub trait CompactLen<T> {
51	/// Returns the compact encoded length for the given value.
52	fn compact_len(val: &T) -> usize;
53}
54
55/// Compact-encoded variant of T. This is more space-efficient but less compute-efficient.
56#[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
72/// Allow foreign structs to be wrap in Compact
73pub trait CompactAs: From<Compact<Self>> {
74	/// A compact-encodable type that should be used as the encoding.
75	type As;
76
77	/// Returns the compact-encodable type.
78	fn encode_as(&self) -> &Self::As;
79
80	/// Decode `Self` from the compact-decoded type.
81	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/// Compact-encoded variant of &'a T. This is more space-efficient but less compute-efficient.
167#[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
211/// Trait that tells you if a given type can be encoded/decoded in a compact way.
212pub trait HasCompact: Sized {
213	/// The compact type; this can be
214	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
245impl<T> CompactLen<T> for WrappedPrimitive<T>
246where
247	T: Copy + Into<u64>,
248{
249	fn compact_len(val: &T) -> usize {
250		let x = (*val).into();
251		1 + if x == 0 {
252			0
253		} else if let Some(l) = (0..8).find(|l| 2_u64.pow(7 * l) <= x && x < 2_u64.pow(7 * (l + 1)))
254		{
255			l
256		} else {
257			8
258		} as usize
259	}
260}
261
262impl<T> Encode for WrappedPrimitive<T>
263where
264	T: Copy + Into<u64>,
265{
266	fn size_hint(&self) -> usize {
267		Self::compact_len(&self.0)
268	}
269
270	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
271		let x = self.0.into();
272		if x == 0 {
273			dest.push_byte(0);
274		} else if let Some(l) = (0..8).find(|l| 2_u64.pow(7 * l) <= x && x < 2_u64.pow(7 * (l + 1)))
275		{
276			dest.push_byte((2_u64.pow(8) - 2_u64.pow(8 - l) + (x / 2_u64.pow(8 * l))) as u8);
277			dest.write(&(x % 2_u64.pow(8 * l)).to_le_bytes()[..l as usize]);
278		} else {
279			dest.push_byte((2_u64.pow(8) - 1) as u8);
280			dest.write(&x.to_le_bytes());
281		}
282	}
283
284	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
285		let mut r = ArrayVecWrapper(ArrayVec::<u8, 9>::new());
286		self.encode_to(&mut r);
287		f(&r.0)
288	}
289}
290
291impl<T> Decode for WrappedPrimitive<T>
292where
293	T: Copy + TryFrom<u64>,
294{
295	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
296		const OUT_OF_RANGE: &str = "Out of range";
297		let v = match input.read_byte()? {
298			0 => 0,
299			0xff => u64::decode(input)?,
300			b => {
301				let l = (0..8).find(|&i| (b & (0b1000_0000 >> i)) == 0).unwrap();
302				let mut buf = [0u8; 8];
303				input.read(&mut buf[..l])?;
304				let rem = (b & ((1 << (7 - l)) - 1)) as u64;
305				u64::from_le_bytes(buf) + (rem << (8 * l))
306			},
307		};
308		let v = T::try_from(v).map_err(|_| Error::from(OUT_OF_RANGE))?;
309		Ok(Self(v))
310	}
311}
312
313impl Encode for CompactRef<'_, u8> {
314	fn size_hint(&self) -> usize {
315		WrappedPrimitive(*self.0).size_hint()
316	}
317
318	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
319		WrappedPrimitive(*self.0).encode_to(dest)
320	}
321
322	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
323		WrappedPrimitive(*self.0).using_encoded(f)
324	}
325}
326
327impl CompactLen<u8> for Compact<u8> {
328	fn compact_len(val: &u8) -> usize {
329		WrappedPrimitive::<u8>::compact_len(val)
330	}
331}
332
333impl Encode for CompactRef<'_, u16> {
334	fn size_hint(&self) -> usize {
335		WrappedPrimitive(*self.0).size_hint()
336	}
337
338	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
339		WrappedPrimitive(*self.0).encode_to(dest)
340	}
341
342	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
343		WrappedPrimitive(*self.0).using_encoded(f)
344	}
345}
346
347impl CompactLen<u16> for Compact<u16> {
348	fn compact_len(val: &u16) -> usize {
349		WrappedPrimitive::<u16>::compact_len(val)
350	}
351}
352
353impl Encode for CompactRef<'_, u32> {
354	fn size_hint(&self) -> usize {
355		WrappedPrimitive(*self.0).size_hint()
356	}
357
358	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
359		WrappedPrimitive(*self.0).encode_to(dest)
360	}
361
362	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
363		WrappedPrimitive(*self.0).using_encoded(f)
364	}
365}
366
367impl CompactLen<u32> for Compact<u32> {
368	fn compact_len(val: &u32) -> usize {
369		WrappedPrimitive::<u32>::compact_len(val)
370	}
371}
372
373impl Encode for CompactRef<'_, u64> {
374	fn size_hint(&self) -> usize {
375		WrappedPrimitive(*self.0).size_hint()
376	}
377
378	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
379		WrappedPrimitive(*self.0).encode_to(dest)
380	}
381
382	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
383		WrappedPrimitive(*self.0).using_encoded(f)
384	}
385}
386
387impl CompactLen<u64> for Compact<u64> {
388	fn compact_len(val: &u64) -> usize {
389		WrappedPrimitive::<u64>::compact_len(val)
390	}
391}
392
393impl Encode for CompactRef<'_, u128> {
394	fn size_hint(&self) -> usize {
395		Compact::<u128>::compact_len(self.0)
396	}
397
398	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
399		let l = (*self.0 & u64::MAX as u128) as u64;
400		let h = (*self.0 >> 64) as u64;
401		WrappedPrimitive::<u64>::encode_to(&WrappedPrimitive(l), dest);
402		WrappedPrimitive::<u64>::encode_to(&WrappedPrimitive(h), dest);
403	}
404}
405
406impl CompactLen<u128> for Compact<u128> {
407	fn compact_len(val: &u128) -> usize {
408		let l = (*val & u64::MAX as u128) as u64;
409		let h = (*val >> 64) as u64;
410		Compact::compact_len(&l) + Compact::compact_len(&h)
411	}
412}
413
414impl Decode for Compact<()> {
415	fn decode<I: Input>(_input: &mut I) -> Result<Self, Error> {
416		Ok(Compact(()))
417	}
418}
419
420impl DecodeWithMemTracking for Compact<()> {}
421
422impl Decode for Compact<u8> {
423	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
424		WrappedPrimitive::<u8>::decode(input).map(|w| Compact(w.0))
425	}
426}
427
428impl DecodeWithMemTracking for Compact<u8> {}
429
430impl Decode for Compact<u16> {
431	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
432		WrappedPrimitive::<u16>::decode(input).map(|w| Compact(w.0))
433	}
434}
435
436impl DecodeWithMemTracking for Compact<u16> {}
437
438impl Decode for Compact<u32> {
439	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
440		WrappedPrimitive::<u32>::decode(input).map(|w| Compact(w.0))
441	}
442}
443
444impl DecodeWithMemTracking for Compact<u32> {}
445
446impl Decode for Compact<u64> {
447	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
448		WrappedPrimitive::<u64>::decode(input).map(|w| Compact(w.0))
449	}
450}
451
452impl DecodeWithMemTracking for Compact<u64> {}
453
454impl Decode for Compact<u128> {
455	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
456		let l = WrappedPrimitive::<u64>::decode(input).map(|w| Compact(w.0))?.0;
457		let h = WrappedPrimitive::<u64>::decode(input).map(|w| Compact(w.0))?.0;
458		Ok(Compact((h as u128) << 64 | l as u128))
459	}
460}
461
462impl DecodeWithMemTracking for Compact<u128> {}
463
464#[cfg(test)]
465mod tests {
466	use super::*;
467
468	#[test]
469	fn compact_128_encoding_works() {
470		let tests = [
471			(0u128, 2),
472			(63, 2),
473			(64, 2),
474			(16383, 3),
475			(16384, 4),
476			(1073741823, 6),
477			(1073741824, 6),
478			((1 << 32) - 1, 6),
479			(1 << 32, 6),
480			(1 << 40, 7), //10
481			(1 << 48, 8),
482			((1 << 56) - 1, 9),
483			(1 << 56, 10),
484			((1 << 64) - 1, 10),
485			(1 << 64, 2),
486			(1 << 72, 3),
487			(1 << 80, 4),
488			(1 << 88, 5),
489			(1 << 96, 6),
490			(1 << 104, 7), //20
491			(1 << 112, 8),
492			((1 << 120) - 1, 17),
493			(1 << 120, 10),
494			(u128::MAX, 18),
495		];
496		for &(n, l) in &tests {
497			let encoded = Compact(n).encode();
498			println!("{}", hex::encode(&encoded));
499			assert_eq!(encoded.len(), l);
500			assert_eq!(Compact::compact_len(&n), l);
501			assert_eq!(<Compact<u128>>::decode(&mut &encoded[..]).unwrap().0, n);
502		}
503	}
504
505	#[test]
506	fn compact_64_encoding_works() {
507		let tests = [
508			(0u64, 1usize),
509			(63, 1),
510			(64, 1),
511			(16383, 2),
512			(16384, 3),
513			(1073741823, 5),
514			(1073741824, 5),
515			((1 << 32) - 1, 5),
516			(1 << 32, 5),
517			(1 << 40, 6),
518			(1 << 48, 7),
519			((1 << 56) - 1, 8),
520			(1 << 56, 9),
521			(u64::MAX, 9),
522		];
523		for &(n, l) in &tests {
524			let encoded = Compact(n).encode();
525			assert_eq!(encoded.len(), l);
526			assert_eq!(Compact::compact_len(&n), l);
527			assert_eq!(<Compact<u64>>::decode(&mut &encoded[..]).unwrap().0, n);
528		}
529	}
530
531	#[test]
532	fn compact_32_encoding_works() {
533		let tests = [
534			(0u32, 1usize),
535			(63, 1),
536			(64, 1),
537			(16383, 2),
538			(16384, 3),
539			(1073741823, 5),
540			(1073741824, 5),
541			(u32::MAX, 5),
542		];
543		for &(n, l) in &tests {
544			let encoded = Compact(n).encode();
545			assert_eq!(encoded.len(), l);
546			assert_eq!(Compact::compact_len(&n), l);
547			assert_eq!(<Compact<u32>>::decode(&mut &encoded[..]).unwrap().0, n);
548		}
549	}
550
551	#[test]
552	fn compact_16_encoding_works() {
553		let tests = [(0u16, 1usize), (63, 1), (64, 1), (16383, 2), (16384, 3), (65535, 3)];
554		for &(n, l) in &tests {
555			let encoded = Compact(n).encode();
556			assert_eq!(encoded.len(), l);
557			assert_eq!(Compact::compact_len(&n), l);
558			assert_eq!(<Compact<u16>>::decode(&mut &encoded[..]).unwrap().0, n);
559		}
560		assert!(<Compact<u16>>::decode(&mut &Compact(65536u32).encode()[..]).is_err());
561	}
562
563	#[test]
564	fn compact_8_encoding_works() {
565		let tests = [(0u8, 1usize), (63, 1), (64, 1), (255, 2)];
566		for &(n, l) in &tests {
567			let encoded = Compact(n).encode();
568			assert_eq!(encoded.len(), l);
569			assert_eq!(Compact::compact_len(&n), l);
570			assert_eq!(<Compact<u8>>::decode(&mut &encoded[..]).unwrap().0, n);
571		}
572		assert!(<Compact<u8>>::decode(&mut &Compact(256u32).encode()[..]).is_err());
573	}
574
575	fn hexify(bytes: &[u8]) -> String {
576		bytes
577			.iter()
578			.map(|ref b| format!("{:02x}", b))
579			.collect::<Vec<String>>()
580			.join(" ")
581	}
582
583	#[test]
584	fn compact_integers_encoded_as_expected() {
585		let tests = [
586			(0u64, "00"),
587			(63, "3f"),
588			(64, "40"),
589			(16383, "bf ff"),
590			(16384, "c0 00 40"),
591			(1073741823, "f0 ff ff ff 3f"),
592			(1073741824, "f0 00 00 00 40"),
593			((1 << 32) - 1, "f0 ff ff ff ff"),
594			(1 << 32, "f1 00 00 00 00"),
595			(1 << 40, "f9 00 00 00 00 00"),
596			(1 << 48, "fd 00 00 00 00 00 00"),
597			((1 << 56) - 1, "fe ff ff ff ff ff ff ff"),
598			(1 << 56, "ff 00 00 00 00 00 00 00 01"),
599			(u64::MAX, "ff ff ff ff ff ff ff ff ff"),
600		];
601		for &(n, s) in &tests {
602			// Verify u64 encoding
603			let encoded = Compact(n).encode();
604			assert_eq!(hexify(&encoded), s);
605			assert_eq!(<Compact<u64>>::decode(&mut &encoded[..]).unwrap().0, n);
606
607			// Verify encodings for lower-size uints are compatible with u64 encoding
608			if n <= u32::MAX as u64 {
609				assert_eq!(<Compact<u32>>::decode(&mut &encoded[..]).unwrap().0, n as u32);
610				let encoded = Compact(n as u32).encode();
611				assert_eq!(hexify(&encoded), s);
612				assert_eq!(<Compact<u64>>::decode(&mut &encoded[..]).unwrap().0, n);
613			}
614			if n <= u16::MAX as u64 {
615				assert_eq!(<Compact<u16>>::decode(&mut &encoded[..]).unwrap().0, n as u16);
616				let encoded = Compact(n as u16).encode();
617				assert_eq!(hexify(&encoded), s);
618				assert_eq!(<Compact<u64>>::decode(&mut &encoded[..]).unwrap().0, n);
619			}
620			if n <= u8::MAX as u64 {
621				assert_eq!(<Compact<u8>>::decode(&mut &encoded[..]).unwrap().0, n as u8);
622				let encoded = Compact(n as u8).encode();
623				assert_eq!(hexify(&encoded), s);
624				assert_eq!(<Compact<u64>>::decode(&mut &encoded[..]).unwrap().0, n);
625			}
626		}
627	}
628
629	#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
630	#[derive(PartialEq, Eq, Clone)]
631	struct Wrapper(u8);
632
633	impl CompactAs for Wrapper {
634		type As = u8;
635		fn encode_as(&self) -> &u8 {
636			&self.0
637		}
638		fn decode_from(x: u8) -> Result<Wrapper, Error> {
639			Ok(Wrapper(x))
640		}
641	}
642
643	impl From<Compact<Wrapper>> for Wrapper {
644		fn from(x: Compact<Wrapper>) -> Wrapper {
645			x.0
646		}
647	}
648
649	#[test]
650	fn compact_as_8_encoding_works() {
651		let tests = [(0u8, 1usize), (63, 1), (64, 1), (255, 2)];
652		for &(n, l) in &tests {
653			let compact: Compact<Wrapper> = Wrapper(n).into();
654			let encoded = compact.encode();
655			assert_eq!(encoded.len(), l);
656			assert_eq!(Compact::compact_len(&n), l);
657			let decoded = <Compact<Wrapper>>::decode(&mut &encoded[..]).unwrap();
658			let wrapper: Wrapper = decoded.into();
659			assert_eq!(wrapper, Wrapper(n));
660		}
661	}
662
663	struct WithCompact<T: HasCompact> {
664		_data: T,
665	}
666
667	#[test]
668	fn compact_as_has_compact() {
669		let _data = WithCompact { _data: Wrapper(1) };
670	}
671
672	#[test]
673	fn compact_using_encoded_arrayvec_size() {
674		Compact(u8::MAX).using_encoded(|_| {});
675		Compact(u16::MAX).using_encoded(|_| {});
676		Compact(u32::MAX).using_encoded(|_| {});
677		Compact(u64::MAX).using_encoded(|_| {});
678		Compact(u128::MAX).using_encoded(|_| {});
679
680		CompactRef(&u8::MAX).using_encoded(|_| {});
681		CompactRef(&u16::MAX).using_encoded(|_| {});
682		CompactRef(&u32::MAX).using_encoded(|_| {});
683		CompactRef(&u64::MAX).using_encoded(|_| {});
684		CompactRef(&u128::MAX).using_encoded(|_| {});
685	}
686
687	#[test]
688	#[should_panic]
689	fn array_vec_output_oob() {
690		let mut v = ArrayVecWrapper(ArrayVec::<u8, 4>::new());
691		v.write(&[1, 2, 3, 4, 5]);
692	}
693
694	#[test]
695	fn array_vec_output() {
696		let mut v = ArrayVecWrapper(ArrayVec::<u8, 4>::new());
697		v.write(&[1, 2, 3, 4]);
698	}
699
700	#[test]
701	fn compact_u64_test() {
702		for a in [
703			u64::MAX,
704			u64::MAX - 1,
705			u64::MAX << 8,
706			(u64::MAX << 8) - 1,
707			u64::MAX << 16,
708			(u64::MAX << 16) - 1,
709		]
710		.iter()
711		{
712			let e = Compact::<u64>::encode(&Compact(*a));
713			let d = Compact::<u64>::decode(&mut &e[..]).unwrap().0;
714			assert_eq!(*a, d);
715		}
716	}
717
718	#[test]
719	fn compact_u128_test() {
720		for a in [u64::MAX as u128, (u64::MAX - 10) as u128, u128::MAX, u128::MAX - 10].iter() {
721			let e = Compact::<u128>::encode(&Compact(*a));
722			let d = Compact::<u128>::decode(&mut &e[..]).unwrap().0;
723			assert_eq!(*a, d);
724		}
725	}
726
727	macro_rules! quick_check_roundtrip {
728		( $( $ty:ty : $test:ident ),* ) => {
729			$(
730				quickcheck::quickcheck! {
731					fn $test(v: $ty) -> bool {
732						let encoded = Compact(v).encode();
733						let deencoded = <Compact<$ty>>::decode(&mut &encoded[..]).unwrap().0;
734
735						v == deencoded
736					}
737				}
738			)*
739		}
740	}
741
742	quick_check_roundtrip! {
743		u8: u8_roundtrip,
744		u16: u16_roundtrip,
745		u32 : u32_roundtrip,
746		u64 : u64_roundtrip,
747		u128 : u128_roundtrip
748	}
749}