parity_scale_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/// Prefix another input with a byte.
50struct PrefixInput<'a, T> {
51	prefix: Option<u8>,
52	input: &'a mut T,
53}
54
55impl<'a, T: 'a + Input> Input for PrefixInput<'a, T> {
56	fn remaining_len(&mut self) -> Result<Option<usize>, Error> {
57		let len = if let Some(len) = self.input.remaining_len()? {
58			Some(len.saturating_add(self.prefix.iter().count()))
59		} else {
60			None
61		};
62		Ok(len)
63	}
64
65	fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
66		if buffer.is_empty() {
67			return Ok(());
68		}
69		match self.prefix.take() {
70			Some(v) => {
71				buffer[0] = v;
72				self.input.read(&mut buffer[1..])
73			},
74			_ => self.input.read(buffer),
75		}
76	}
77}
78
79/// Something that can return the compact encoded length for a given value.
80pub trait CompactLen<T> {
81	/// Returns the compact encoded length for the given value.
82	fn compact_len(val: &T) -> usize;
83}
84
85/// Compact-encoded variant of T. This is more space-efficient but less compute-efficient.
86#[derive(Eq, PartialEq, Clone, Copy, Ord, PartialOrd)]
87#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
88pub struct Compact<T>(pub T);
89
90impl<T> From<T> for Compact<T> {
91	fn from(x: T) -> Compact<T> {
92		Compact(x)
93	}
94}
95
96impl<'a, T: Copy> From<&'a T> for Compact<T> {
97	fn from(x: &'a T) -> Compact<T> {
98		Compact(*x)
99	}
100}
101
102/// Allow foreign structs to be wrap in Compact
103pub trait CompactAs: From<Compact<Self>> {
104	/// A compact-encodable type that should be used as the encoding.
105	type As;
106
107	/// Returns the compact-encodable type.
108	fn encode_as(&self) -> &Self::As;
109
110	/// Decode `Self` from the compact-decoded type.
111	fn decode_from(_: Self::As) -> Result<Self, Error>;
112}
113
114impl<T> EncodeLike for Compact<T> where for<'a> CompactRef<'a, T>: Encode {}
115
116impl<T> Encode for Compact<T>
117where
118	for<'a> CompactRef<'a, T>: Encode,
119{
120	fn size_hint(&self) -> usize {
121		CompactRef(&self.0).size_hint()
122	}
123
124	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
125		CompactRef(&self.0).encode_to(dest)
126	}
127
128	fn encode(&self) -> Vec<u8> {
129		CompactRef(&self.0).encode()
130	}
131
132	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
133		CompactRef(&self.0).using_encoded(f)
134	}
135}
136
137impl<T> EncodeLike for CompactRef<'_, T>
138where
139	T: CompactAs,
140	for<'b> CompactRef<'b, T::As>: Encode,
141{
142}
143
144impl<T> Encode for CompactRef<'_, T>
145where
146	T: CompactAs,
147	for<'b> CompactRef<'b, T::As>: Encode,
148{
149	fn size_hint(&self) -> usize {
150		CompactRef(self.0.encode_as()).size_hint()
151	}
152
153	fn encode_to<Out: Output + ?Sized>(&self, dest: &mut Out) {
154		CompactRef(self.0.encode_as()).encode_to(dest)
155	}
156
157	fn encode(&self) -> Vec<u8> {
158		CompactRef(self.0.encode_as()).encode()
159	}
160
161	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
162		CompactRef(self.0.encode_as()).using_encoded(f)
163	}
164}
165
166impl<T> Decode for Compact<T>
167where
168	T: CompactAs,
169	Compact<T::As>: Decode,
170{
171	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
172		let as_ = Compact::<T::As>::decode(input)?;
173		Ok(Compact(<T as CompactAs>::decode_from(as_.0)?))
174	}
175}
176
177impl<T> DecodeWithMemTracking for Compact<T>
178where
179	T: CompactAs,
180	Compact<T::As>: DecodeWithMemTracking,
181{
182}
183
184macro_rules! impl_from_compact {
185	( $( $ty:ty ),* ) => {
186		$(
187			impl From<Compact<$ty>> for $ty {
188				fn from(x: Compact<$ty>) -> $ty { x.0 }
189			}
190		)*
191	}
192}
193
194impl_from_compact! { (), u8, u16, u32, u64, u128 }
195
196/// Compact-encoded variant of &'a T. This is more space-efficient but less compute-efficient.
197#[derive(Eq, PartialEq, Clone, Copy)]
198pub struct CompactRef<'a, T>(pub &'a T);
199
200impl<'a, T> From<&'a T> for CompactRef<'a, T> {
201	fn from(x: &'a T) -> Self {
202		CompactRef(x)
203	}
204}
205
206impl<T> core::fmt::Debug for Compact<T>
207where
208	T: core::fmt::Debug,
209{
210	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
211		self.0.fmt(f)
212	}
213}
214
215#[cfg(feature = "serde")]
216impl<T> serde::Serialize for Compact<T>
217where
218	T: serde::Serialize,
219{
220	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
221	where
222		S: serde::Serializer,
223	{
224		T::serialize(&self.0, serializer)
225	}
226}
227
228#[cfg(feature = "serde")]
229impl<'de, T> serde::Deserialize<'de> for Compact<T>
230where
231	T: serde::Deserialize<'de>,
232{
233	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
234	where
235		D: serde::Deserializer<'de>,
236	{
237		T::deserialize(deserializer).map(Compact)
238	}
239}
240
241/// Trait that tells you if a given type can be encoded/decoded in a compact way.
242pub trait HasCompact: Sized {
243	/// The compact type; this can be
244	type Type: for<'a> EncodeAsRef<'a, Self> + Decode + From<Self> + Into<Self>;
245}
246
247impl<'a, T: 'a> EncodeAsRef<'a, T> for Compact<T>
248where
249	CompactRef<'a, T>: Encode + From<&'a T>,
250{
251	type RefType = CompactRef<'a, T>;
252}
253
254impl<T: 'static> HasCompact for T
255where
256	Compact<T>: for<'a> EncodeAsRef<'a, T> + Decode + From<Self> + Into<Self>,
257{
258	type Type = Compact<T>;
259}
260
261impl Encode for CompactRef<'_, ()> {
262	fn encode_to<W: Output + ?Sized>(&self, _dest: &mut W) {}
263
264	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
265		f(&[])
266	}
267
268	fn encode(&self) -> Vec<u8> {
269		Vec::new()
270	}
271}
272
273impl Encode for CompactRef<'_, u8> {
274	fn size_hint(&self) -> usize {
275		Compact::compact_len(self.0)
276	}
277
278	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
279		match self.0 {
280			0..=0b0011_1111 => dest.push_byte(self.0 << 2),
281			_ => ((u16::from(*self.0) << 2) | 0b01).encode_to(dest),
282		}
283	}
284
285	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
286		let mut r = ArrayVecWrapper(ArrayVec::<u8, 2>::new());
287		self.encode_to(&mut r);
288		f(&r.0)
289	}
290}
291
292impl CompactLen<u8> for Compact<u8> {
293	fn compact_len(val: &u8) -> usize {
294		match val {
295			0..=0b0011_1111 => 1,
296			_ => 2,
297		}
298	}
299}
300
301impl Encode for CompactRef<'_, u16> {
302	fn size_hint(&self) -> usize {
303		Compact::compact_len(self.0)
304	}
305
306	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
307		match self.0 {
308			0..=0b0011_1111 => dest.push_byte((*self.0 as u8) << 2),
309			0..=0b0011_1111_1111_1111 => ((*self.0 << 2) | 0b01).encode_to(dest),
310			_ => ((u32::from(*self.0) << 2) | 0b10).encode_to(dest),
311		}
312	}
313
314	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
315		let mut r = ArrayVecWrapper(ArrayVec::<u8, 4>::new());
316		self.encode_to(&mut r);
317		f(&r.0)
318	}
319}
320
321impl CompactLen<u16> for Compact<u16> {
322	fn compact_len(val: &u16) -> usize {
323		match val {
324			0..=0b0011_1111 => 1,
325			0..=0b0011_1111_1111_1111 => 2,
326			_ => 4,
327		}
328	}
329}
330
331impl Encode for CompactRef<'_, u32> {
332	fn size_hint(&self) -> usize {
333		Compact::compact_len(self.0)
334	}
335
336	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
337		match self.0 {
338			0..=0b0011_1111 => dest.push_byte((*self.0 as u8) << 2),
339			0..=0b0011_1111_1111_1111 => (((*self.0 as u16) << 2) | 0b01).encode_to(dest),
340			0..=0b0011_1111_1111_1111_1111_1111_1111_1111 =>
341				((*self.0 << 2) | 0b10).encode_to(dest),
342			_ => {
343				dest.push_byte(0b11);
344				self.0.encode_to(dest);
345			},
346		}
347	}
348
349	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
350		let mut r = ArrayVecWrapper(ArrayVec::<u8, 5>::new());
351		self.encode_to(&mut r);
352		f(&r.0)
353	}
354}
355
356impl CompactLen<u32> for Compact<u32> {
357	fn compact_len(val: &u32) -> usize {
358		match val {
359			0..=0b0011_1111 => 1,
360			0..=0b0011_1111_1111_1111 => 2,
361			0..=0b0011_1111_1111_1111_1111_1111_1111_1111 => 4,
362			_ => 5,
363		}
364	}
365}
366
367impl Encode for CompactRef<'_, u64> {
368	fn size_hint(&self) -> usize {
369		Compact::compact_len(self.0)
370	}
371
372	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
373		match self.0 {
374			0..=0b0011_1111 => dest.push_byte((*self.0 as u8) << 2),
375			0..=0b0011_1111_1111_1111 => (((*self.0 as u16) << 2) | 0b01).encode_to(dest),
376			0..=0b0011_1111_1111_1111_1111_1111_1111_1111 =>
377				(((*self.0 as u32) << 2) | 0b10).encode_to(dest),
378			_ => {
379				let bytes_needed = 8 - self.0.leading_zeros() / 8;
380				assert!(
381					bytes_needed >= 4,
382					"Previous match arm matches anyting less than 2^30; qed"
383				);
384				dest.push_byte(0b11 + ((bytes_needed - 4) << 2) as u8);
385				let mut v = *self.0;
386				for _ in 0..bytes_needed {
387					dest.push_byte(v as u8);
388					v >>= 8;
389				}
390				assert_eq!(v, 0, "shifted sufficient bits right to lead only leading zeros; qed")
391			},
392		}
393	}
394
395	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
396		let mut r = ArrayVecWrapper(ArrayVec::<u8, 9>::new());
397		self.encode_to(&mut r);
398		f(&r.0)
399	}
400}
401
402impl CompactLen<u64> for Compact<u64> {
403	fn compact_len(val: &u64) -> usize {
404		match val {
405			0..=0b0011_1111 => 1,
406			0..=0b0011_1111_1111_1111 => 2,
407			0..=0b0011_1111_1111_1111_1111_1111_1111_1111 => 4,
408			_ => (8 - val.leading_zeros() / 8) as usize + 1,
409		}
410	}
411}
412
413impl Encode for CompactRef<'_, u128> {
414	fn size_hint(&self) -> usize {
415		Compact::compact_len(self.0)
416	}
417
418	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
419		match self.0 {
420			0..=0b0011_1111 => dest.push_byte((*self.0 as u8) << 2),
421			0..=0b0011_1111_1111_1111 => (((*self.0 as u16) << 2) | 0b01).encode_to(dest),
422			0..=0b0011_1111_1111_1111_1111_1111_1111_1111 =>
423				(((*self.0 as u32) << 2) | 0b10).encode_to(dest),
424			_ => {
425				let bytes_needed = 16 - self.0.leading_zeros() / 8;
426				assert!(
427					bytes_needed >= 4,
428					"Previous match arm matches anyting less than 2^30; qed"
429				);
430				dest.push_byte(0b11 + ((bytes_needed - 4) << 2) as u8);
431				let mut v = *self.0;
432				for _ in 0..bytes_needed {
433					dest.push_byte(v as u8);
434					v >>= 8;
435				}
436				assert_eq!(v, 0, "shifted sufficient bits right to lead only leading zeros; qed")
437			},
438		}
439	}
440
441	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
442		let mut r = ArrayVecWrapper(ArrayVec::<u8, 17>::new());
443		self.encode_to(&mut r);
444		f(&r.0)
445	}
446}
447
448impl CompactLen<u128> for Compact<u128> {
449	fn compact_len(val: &u128) -> usize {
450		match val {
451			0..=0b0011_1111 => 1,
452			0..=0b0011_1111_1111_1111 => 2,
453			0..=0b0011_1111_1111_1111_1111_1111_1111_1111 => 4,
454			_ => (16 - val.leading_zeros() / 8) as usize + 1,
455		}
456	}
457}
458
459impl Decode for Compact<()> {
460	fn decode<I: Input>(_input: &mut I) -> Result<Self, Error> {
461		Ok(Compact(()))
462	}
463}
464
465impl DecodeWithMemTracking for Compact<()> {}
466
467const U8_OUT_OF_RANGE: &str = "out of range decoding Compact<u8>";
468const U16_OUT_OF_RANGE: &str = "out of range decoding Compact<u16>";
469const U32_OUT_OF_RANGE: &str = "out of range decoding Compact<u32>";
470const U64_OUT_OF_RANGE: &str = "out of range decoding Compact<u64>";
471const U128_OUT_OF_RANGE: &str = "out of range decoding Compact<u128>";
472
473impl Decode for Compact<u8> {
474	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
475		let prefix = input.read_byte()?;
476		Ok(Compact(match prefix % 4 {
477			0 => prefix >> 2,
478			1 => {
479				let x = u16::decode(&mut PrefixInput { prefix: Some(prefix), input })? >> 2;
480				if x > 0b0011_1111 && x <= 255 {
481					x as u8
482				} else {
483					return Err(U8_OUT_OF_RANGE.into());
484				}
485			},
486			_ => return Err("unexpected prefix decoding Compact<u8>".into()),
487		}))
488	}
489}
490
491impl DecodeWithMemTracking for Compact<u8> {}
492
493impl Decode for Compact<u16> {
494	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
495		let prefix = input.read_byte()?;
496		Ok(Compact(match prefix % 4 {
497			0 => u16::from(prefix) >> 2,
498			1 => {
499				let x = u16::decode(&mut PrefixInput { prefix: Some(prefix), input })? >> 2;
500				if x > 0b0011_1111 && x <= 0b0011_1111_1111_1111 {
501					x
502				} else {
503					return Err(U16_OUT_OF_RANGE.into());
504				}
505			},
506			2 => {
507				let x = u32::decode(&mut PrefixInput { prefix: Some(prefix), input })? >> 2;
508				if x > 0b0011_1111_1111_1111 && x < 65536 {
509					x as u16
510				} else {
511					return Err(U16_OUT_OF_RANGE.into());
512				}
513			},
514			_ => return Err("unexpected prefix decoding Compact<u16>".into()),
515		}))
516	}
517}
518
519impl DecodeWithMemTracking for Compact<u16> {}
520
521impl Decode for Compact<u32> {
522	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
523		let prefix = input.read_byte()?;
524		Ok(Compact(match prefix % 4 {
525			0 => u32::from(prefix) >> 2,
526			1 => {
527				let x = u16::decode(&mut PrefixInput { prefix: Some(prefix), input })? >> 2;
528				if x > 0b0011_1111 && x <= 0b0011_1111_1111_1111 {
529					u32::from(x)
530				} else {
531					return Err(U32_OUT_OF_RANGE.into());
532				}
533			},
534			2 => {
535				let x = u32::decode(&mut PrefixInput { prefix: Some(prefix), input })? >> 2;
536				if x > 0b0011_1111_1111_1111 && x <= u32::MAX >> 2 {
537					x
538				} else {
539					return Err(U32_OUT_OF_RANGE.into());
540				}
541			},
542			3 => {
543				if prefix >> 2 == 0 {
544					// just 4 bytes. ok.
545					let x = u32::decode(input)?;
546					if x > u32::MAX >> 2 {
547						x
548					} else {
549						return Err(U32_OUT_OF_RANGE.into());
550					}
551				} else {
552					// Out of range for a 32-bit quantity.
553					return Err(U32_OUT_OF_RANGE.into());
554				}
555			},
556			_ => unreachable!(),
557		}))
558	}
559}
560
561impl DecodeWithMemTracking for Compact<u32> {}
562
563impl Decode for Compact<u64> {
564	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
565		let prefix = input.read_byte()?;
566		Ok(Compact(match prefix % 4 {
567			0 => u64::from(prefix) >> 2,
568			1 => {
569				let x = u16::decode(&mut PrefixInput { prefix: Some(prefix), input })? >> 2;
570				if x > 0b0011_1111 && x <= 0b0011_1111_1111_1111 {
571					u64::from(x)
572				} else {
573					return Err(U64_OUT_OF_RANGE.into());
574				}
575			},
576			2 => {
577				let x = u32::decode(&mut PrefixInput { prefix: Some(prefix), input })? >> 2;
578				if x > 0b0011_1111_1111_1111 && x <= u32::MAX >> 2 {
579					u64::from(x)
580				} else {
581					return Err(U64_OUT_OF_RANGE.into());
582				}
583			},
584			3 => match (prefix >> 2) + 4 {
585				4 => {
586					let x = u32::decode(input)?;
587					if x > u32::MAX >> 2 {
588						u64::from(x)
589					} else {
590						return Err(U64_OUT_OF_RANGE.into());
591					}
592				},
593				8 => {
594					let x = u64::decode(input)?;
595					if x > u64::MAX >> 8 {
596						x
597					} else {
598						return Err(U64_OUT_OF_RANGE.into());
599					}
600				},
601				x if x > 8 => return Err("unexpected prefix decoding Compact<u64>".into()),
602				bytes_needed => {
603					let mut res = 0;
604					for i in 0..bytes_needed {
605						res |= u64::from(input.read_byte()?) << (i * 8);
606					}
607					if res > u64::MAX >> ((8 - bytes_needed + 1) * 8) {
608						res
609					} else {
610						return Err(U64_OUT_OF_RANGE.into());
611					}
612				},
613			},
614			_ => unreachable!(),
615		}))
616	}
617}
618
619impl DecodeWithMemTracking for Compact<u64> {}
620
621impl Decode for Compact<u128> {
622	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
623		let prefix = input.read_byte()?;
624		Ok(Compact(match prefix % 4 {
625			0 => u128::from(prefix) >> 2,
626			1 => {
627				let x = u16::decode(&mut PrefixInput { prefix: Some(prefix), input })? >> 2;
628				if x > 0b0011_1111 && x <= 0b0011_1111_1111_1111 {
629					u128::from(x)
630				} else {
631					return Err(U128_OUT_OF_RANGE.into());
632				}
633			},
634			2 => {
635				let x = u32::decode(&mut PrefixInput { prefix: Some(prefix), input })? >> 2;
636				if x > 0b0011_1111_1111_1111 && x <= u32::MAX >> 2 {
637					u128::from(x)
638				} else {
639					return Err(U128_OUT_OF_RANGE.into());
640				}
641			},
642			3 => match (prefix >> 2) + 4 {
643				4 => {
644					let x = u32::decode(input)?;
645					if x > u32::MAX >> 2 {
646						u128::from(x)
647					} else {
648						return Err(U128_OUT_OF_RANGE.into());
649					}
650				},
651				8 => {
652					let x = u64::decode(input)?;
653					if x > u64::MAX >> 8 {
654						u128::from(x)
655					} else {
656						return Err(U128_OUT_OF_RANGE.into());
657					}
658				},
659				16 => {
660					let x = u128::decode(input)?;
661					if x > u128::MAX >> 8 {
662						x
663					} else {
664						return Err(U128_OUT_OF_RANGE.into());
665					}
666				},
667				x if x > 16 => return Err("unexpected prefix decoding Compact<u128>".into()),
668				bytes_needed => {
669					let mut res = 0;
670					for i in 0..bytes_needed {
671						res |= u128::from(input.read_byte()?) << (i * 8);
672					}
673					if res > u128::MAX >> ((16 - bytes_needed + 1) * 8) {
674						res
675					} else {
676						return Err(U128_OUT_OF_RANGE.into());
677					}
678				},
679			},
680			_ => unreachable!(),
681		}))
682	}
683}
684
685impl DecodeWithMemTracking for Compact<u128> {}
686
687#[cfg(test)]
688mod tests {
689	use super::*;
690
691	#[test]
692	fn prefix_input_empty_read_unchanged() {
693		let mut input = PrefixInput { prefix: Some(1), input: &mut &vec![2, 3, 4][..] };
694		assert_eq!(input.remaining_len(), Ok(Some(4)));
695		let mut empty_buf = [];
696		assert_eq!(input.read(&mut empty_buf[..]), Ok(()));
697		assert_eq!(input.remaining_len(), Ok(Some(4)));
698		assert_eq!(input.read_byte(), Ok(1));
699	}
700
701	#[test]
702	fn compact_128_encoding_works() {
703		let tests = [
704			(0u128, 1usize),
705			(63, 1),
706			(64, 2),
707			(16383, 2),
708			(16384, 4),
709			(1073741823, 4),
710			(1073741824, 5),
711			((1 << 32) - 1, 5),
712			(1 << 32, 6),
713			(1 << 40, 7),
714			(1 << 48, 8),
715			((1 << 56) - 1, 8),
716			(1 << 56, 9),
717			((1 << 64) - 1, 9),
718			(1 << 64, 10),
719			(1 << 72, 11),
720			(1 << 80, 12),
721			(1 << 88, 13),
722			(1 << 96, 14),
723			(1 << 104, 15),
724			(1 << 112, 16),
725			((1 << 120) - 1, 16),
726			(1 << 120, 17),
727			(u128::MAX, 17),
728		];
729		for &(n, l) in &tests {
730			let encoded = Compact(n).encode();
731			assert_eq!(encoded.len(), l);
732			assert_eq!(Compact::compact_len(&n), l);
733			assert_eq!(<Compact<u128>>::decode(&mut &encoded[..]).unwrap().0, n);
734		}
735	}
736
737	#[test]
738	fn compact_64_encoding_works() {
739		let tests = [
740			(0u64, 1usize),
741			(63, 1),
742			(64, 2),
743			(16383, 2),
744			(16384, 4),
745			(1073741823, 4),
746			(1073741824, 5),
747			((1 << 32) - 1, 5),
748			(1 << 32, 6),
749			(1 << 40, 7),
750			(1 << 48, 8),
751			((1 << 56) - 1, 8),
752			(1 << 56, 9),
753			(u64::MAX, 9),
754		];
755		for &(n, l) in &tests {
756			let encoded = Compact(n).encode();
757			assert_eq!(encoded.len(), l);
758			assert_eq!(Compact::compact_len(&n), l);
759			assert_eq!(<Compact<u64>>::decode(&mut &encoded[..]).unwrap().0, n);
760		}
761	}
762
763	#[test]
764	fn compact_32_encoding_works() {
765		let tests = [
766			(0u32, 1usize),
767			(63, 1),
768			(64, 2),
769			(16383, 2),
770			(16384, 4),
771			(1073741823, 4),
772			(1073741824, 5),
773			(u32::MAX, 5),
774		];
775		for &(n, l) in &tests {
776			let encoded = Compact(n).encode();
777			assert_eq!(encoded.len(), l);
778			assert_eq!(Compact::compact_len(&n), l);
779			assert_eq!(<Compact<u32>>::decode(&mut &encoded[..]).unwrap().0, n);
780		}
781	}
782
783	#[test]
784	fn compact_16_encoding_works() {
785		let tests = [(0u16, 1usize), (63, 1), (64, 2), (16383, 2), (16384, 4), (65535, 4)];
786		for &(n, l) in &tests {
787			let encoded = Compact(n).encode();
788			assert_eq!(encoded.len(), l);
789			assert_eq!(Compact::compact_len(&n), l);
790			assert_eq!(<Compact<u16>>::decode(&mut &encoded[..]).unwrap().0, n);
791		}
792		assert!(<Compact<u16>>::decode(&mut &Compact(65536u32).encode()[..]).is_err());
793	}
794
795	#[test]
796	fn compact_8_encoding_works() {
797		let tests = [(0u8, 1usize), (63, 1), (64, 2), (255, 2)];
798		for &(n, l) in &tests {
799			let encoded = Compact(n).encode();
800			assert_eq!(encoded.len(), l);
801			assert_eq!(Compact::compact_len(&n), l);
802			assert_eq!(<Compact<u8>>::decode(&mut &encoded[..]).unwrap().0, n);
803		}
804		assert!(<Compact<u8>>::decode(&mut &Compact(256u32).encode()[..]).is_err());
805	}
806
807	fn hexify(bytes: &[u8]) -> String {
808		bytes
809			.iter()
810			.map(|ref b| format!("{:02x}", b))
811			.collect::<Vec<String>>()
812			.join(" ")
813	}
814
815	#[test]
816	fn compact_integers_encoded_as_expected() {
817		let tests = [
818			(0u64, "00"),
819			(63, "fc"),
820			(64, "01 01"),
821			(16383, "fd ff"),
822			(16384, "02 00 01 00"),
823			(1073741823, "fe ff ff ff"),
824			(1073741824, "03 00 00 00 40"),
825			((1 << 32) - 1, "03 ff ff ff ff"),
826			(1 << 32, "07 00 00 00 00 01"),
827			(1 << 40, "0b 00 00 00 00 00 01"),
828			(1 << 48, "0f 00 00 00 00 00 00 01"),
829			((1 << 56) - 1, "0f ff ff ff ff ff ff ff"),
830			(1 << 56, "13 00 00 00 00 00 00 00 01"),
831			(u64::MAX, "13 ff ff ff ff ff ff ff ff"),
832		];
833		for &(n, s) in &tests {
834			// Verify u64 encoding
835			let encoded = Compact(n).encode();
836			assert_eq!(hexify(&encoded), s);
837			assert_eq!(<Compact<u64>>::decode(&mut &encoded[..]).unwrap().0, n);
838
839			// Verify encodings for lower-size uints are compatible with u64 encoding
840			if n <= u32::MAX as u64 {
841				assert_eq!(<Compact<u32>>::decode(&mut &encoded[..]).unwrap().0, n as u32);
842				let encoded = Compact(n as u32).encode();
843				assert_eq!(hexify(&encoded), s);
844				assert_eq!(<Compact<u64>>::decode(&mut &encoded[..]).unwrap().0, n);
845			}
846			if n <= u16::MAX as u64 {
847				assert_eq!(<Compact<u16>>::decode(&mut &encoded[..]).unwrap().0, n as u16);
848				let encoded = Compact(n as u16).encode();
849				assert_eq!(hexify(&encoded), s);
850				assert_eq!(<Compact<u64>>::decode(&mut &encoded[..]).unwrap().0, n);
851			}
852			if n <= u8::MAX as u64 {
853				assert_eq!(<Compact<u8>>::decode(&mut &encoded[..]).unwrap().0, n as u8);
854				let encoded = Compact(n as u8).encode();
855				assert_eq!(hexify(&encoded), s);
856				assert_eq!(<Compact<u64>>::decode(&mut &encoded[..]).unwrap().0, n);
857			}
858		}
859	}
860
861	#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
862	#[derive(PartialEq, Eq, Clone)]
863	struct Wrapper(u8);
864
865	impl CompactAs for Wrapper {
866		type As = u8;
867		fn encode_as(&self) -> &u8 {
868			&self.0
869		}
870		fn decode_from(x: u8) -> Result<Wrapper, Error> {
871			Ok(Wrapper(x))
872		}
873	}
874
875	impl From<Compact<Wrapper>> for Wrapper {
876		fn from(x: Compact<Wrapper>) -> Wrapper {
877			x.0
878		}
879	}
880
881	#[test]
882	fn compact_as_8_encoding_works() {
883		let tests = [(0u8, 1usize), (63, 1), (64, 2), (255, 2)];
884		for &(n, l) in &tests {
885			let compact: Compact<Wrapper> = Wrapper(n).into();
886			let encoded = compact.encode();
887			assert_eq!(encoded.len(), l);
888			assert_eq!(Compact::compact_len(&n), l);
889			let decoded = <Compact<Wrapper>>::decode(&mut &encoded[..]).unwrap();
890			let wrapper: Wrapper = decoded.into();
891			assert_eq!(wrapper, Wrapper(n));
892		}
893	}
894
895	struct WithCompact<T: HasCompact> {
896		_data: T,
897	}
898
899	#[test]
900	fn compact_as_has_compact() {
901		let _data = WithCompact { _data: Wrapper(1) };
902	}
903
904	#[test]
905	fn compact_using_encoded_arrayvec_size() {
906		Compact(u8::MAX).using_encoded(|_| {});
907		Compact(u16::MAX).using_encoded(|_| {});
908		Compact(u32::MAX).using_encoded(|_| {});
909		Compact(u64::MAX).using_encoded(|_| {});
910		Compact(u128::MAX).using_encoded(|_| {});
911
912		CompactRef(&u8::MAX).using_encoded(|_| {});
913		CompactRef(&u16::MAX).using_encoded(|_| {});
914		CompactRef(&u32::MAX).using_encoded(|_| {});
915		CompactRef(&u64::MAX).using_encoded(|_| {});
916		CompactRef(&u128::MAX).using_encoded(|_| {});
917	}
918
919	#[test]
920	#[should_panic]
921	fn array_vec_output_oob() {
922		let mut v = ArrayVecWrapper(ArrayVec::<u8, 4>::new());
923		v.write(&[1, 2, 3, 4, 5]);
924	}
925
926	#[test]
927	fn array_vec_output() {
928		let mut v = ArrayVecWrapper(ArrayVec::<u8, 4>::new());
929		v.write(&[1, 2, 3, 4]);
930	}
931
932	macro_rules! check_bound {
933		( $m:expr, $ty:ty, $typ1:ty, [ $(($ty2:ty, $ty2_err:expr)),* ]) => {
934			$(
935				check_bound!($m, $ty, $typ1, $ty2, $ty2_err);
936			)*
937		};
938		( $m:expr, $ty:ty, $typ1:ty, $ty2:ty, $ty2_err:expr) => {
939			let enc = ((<$ty>::MAX >> 2) as $typ1 << 2) | $m;
940			assert_eq!(Compact::<$ty2>::decode(&mut &enc.to_le_bytes()[..]),
941				Err($ty2_err.into()));
942		};
943	}
944	macro_rules! check_bound_u32 {
945		( [ $(($ty2:ty, $ty2_err:expr)),* ]) => {
946			$(
947				check_bound_u32!($ty2, $ty2_err);
948			)*
949		};
950		( $ty2:ty, $ty2_err:expr ) => {
951			assert_eq!(Compact::<$ty2>::decode(&mut &[0b11, 0xff, 0xff, 0xff, 0xff >> 2][..]),
952				Err($ty2_err.into()));
953		};
954	}
955	macro_rules! check_bound_high {
956		( $m:expr, [ $(($ty2:ty, $ty2_err:expr)),* ]) => {
957			$(
958				check_bound_high!($m, $ty2, $ty2_err);
959			)*
960		};
961		( $s:expr, $ty2:ty, $ty2_err:expr) => {
962			let mut dest = Vec::new();
963			dest.push(0b11 + (($s - 4) << 2) as u8);
964			for _ in 0..($s - 1) {
965				dest.push(u8::MAX);
966			}
967			dest.push(0);
968			assert_eq!(Compact::<$ty2>::decode(&mut &dest[..]),
969				Err($ty2_err.into()));
970		};
971	}
972
973	#[test]
974	fn compact_u64_test() {
975		for a in [
976			u64::MAX,
977			u64::MAX - 1,
978			u64::MAX << 8,
979			(u64::MAX << 8) - 1,
980			u64::MAX << 16,
981			(u64::MAX << 16) - 1,
982		]
983		.iter()
984		{
985			let e = Compact::<u64>::encode(&Compact(*a));
986			let d = Compact::<u64>::decode(&mut &e[..]).unwrap().0;
987			assert_eq!(*a, d);
988		}
989	}
990
991	#[test]
992	fn compact_u128_test() {
993		for a in [u64::MAX as u128, (u64::MAX - 10) as u128, u128::MAX, u128::MAX - 10].iter() {
994			let e = Compact::<u128>::encode(&Compact(*a));
995			let d = Compact::<u128>::decode(&mut &e[..]).unwrap().0;
996			assert_eq!(*a, d);
997		}
998	}
999
1000	#[test]
1001	fn should_avoid_overlapping_definition() {
1002		check_bound!(
1003			0b01,
1004			u8,
1005			u16,
1006			[
1007				(u8, U8_OUT_OF_RANGE),
1008				(u16, U16_OUT_OF_RANGE),
1009				(u32, U32_OUT_OF_RANGE),
1010				(u64, U64_OUT_OF_RANGE),
1011				(u128, U128_OUT_OF_RANGE)
1012			]
1013		);
1014		check_bound!(
1015			0b10,
1016			u16,
1017			u32,
1018			[
1019				(u16, U16_OUT_OF_RANGE),
1020				(u32, U32_OUT_OF_RANGE),
1021				(u64, U64_OUT_OF_RANGE),
1022				(u128, U128_OUT_OF_RANGE)
1023			]
1024		);
1025		check_bound_u32!([
1026			(u32, U32_OUT_OF_RANGE),
1027			(u64, U64_OUT_OF_RANGE),
1028			(u128, U128_OUT_OF_RANGE)
1029		]);
1030		for i in 5..=8 {
1031			check_bound_high!(i, [(u64, U64_OUT_OF_RANGE), (u128, U128_OUT_OF_RANGE)]);
1032		}
1033		for i in 8..=16 {
1034			check_bound_high!(i, [(u128, U128_OUT_OF_RANGE)]);
1035		}
1036	}
1037
1038	macro_rules! quick_check_roundtrip {
1039		( $( $ty:ty : $test:ident ),* ) => {
1040			$(
1041				quickcheck::quickcheck! {
1042					fn $test(v: $ty) -> bool {
1043						let encoded = Compact(v).encode();
1044						let deencoded = <Compact<$ty>>::decode(&mut &encoded[..]).unwrap().0;
1045
1046						v == deencoded
1047					}
1048				}
1049			)*
1050		}
1051	}
1052
1053	quick_check_roundtrip! {
1054		u8: u8_roundtrip,
1055		u16: u16_roundtrip,
1056		u32 : u32_roundtrip,
1057		u64 : u64_roundtrip,
1058		u128 : u128_roundtrip
1059	}
1060}