reference_trie/
substrate.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9//     http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17//! Codec and layout directly copy-pasted from substrate with minimal modifications.
18
19use core::{borrow::Borrow, iter::once, marker::PhantomData, ops::Range};
20use hash_db::Hasher;
21use parity_scale_codec as codec;
22use parity_scale_codec::{Compact, Decode, Encode, Input, Output};
23use trie_db::{
24	nibble_ops,
25	node::{NibbleSlicePlan, NodeHandlePlan, NodePlan, Value, ValuePlan},
26	ChildReference, NodeCodec as NodeCodecT, TrieConfiguration, TrieLayout,
27};
28
29/// Constants used into trie simplification codec.
30mod trie_constants {
31	const FIRST_PREFIX: u8 = 0b_00 << 6;
32	pub const LEAF_PREFIX_MASK: u8 = 0b_01 << 6;
33	pub const BRANCH_WITHOUT_MASK: u8 = 0b_10 << 6;
34	pub const BRANCH_WITH_MASK: u8 = 0b_11 << 6;
35	pub const EMPTY_TRIE: u8 = FIRST_PREFIX | (0b_00 << 4);
36	pub const ALT_HASHING_LEAF_PREFIX_MASK: u8 = FIRST_PREFIX | (0b_1 << 5);
37	pub const ALT_HASHING_BRANCH_WITH_MASK: u8 = FIRST_PREFIX | (0b_01 << 4);
38	pub const ESCAPE_COMPACT_HEADER: u8 = EMPTY_TRIE | 0b_00_01;
39}
40
41pub const TRIE_VALUE_NODE_THRESHOLD: u32 = 33;
42
43/// Codec-flavored TrieStream.
44#[derive(Default, Clone)]
45pub struct TrieStream {
46	/// Current node buffer.
47	buffer: Vec<u8>,
48}
49
50fn branch_node_bit_mask(has_children: impl Iterator<Item = bool>) -> (u8, u8) {
51	let mut bitmap: u16 = 0;
52	let mut cursor: u16 = 1;
53	for v in has_children {
54		if v {
55			bitmap |= cursor
56		}
57		cursor <<= 1;
58	}
59	((bitmap % 256) as u8, (bitmap / 256) as u8)
60}
61
62/// Create a leaf/branch node, encoding a number of nibbles.
63fn fuse_nibbles_node(nibbles: &[u8], kind: NodeKind) -> impl Iterator<Item = u8> + '_ {
64	let size = nibbles.len();
65	let iter_start = match kind {
66		NodeKind::Leaf => size_and_prefix_iterator(size, trie_constants::LEAF_PREFIX_MASK, 2),
67		NodeKind::BranchNoValue =>
68			size_and_prefix_iterator(size, trie_constants::BRANCH_WITHOUT_MASK, 2),
69		NodeKind::BranchWithValue =>
70			size_and_prefix_iterator(size, trie_constants::BRANCH_WITH_MASK, 2),
71		NodeKind::HashedValueLeaf =>
72			size_and_prefix_iterator(size, trie_constants::ALT_HASHING_LEAF_PREFIX_MASK, 3),
73		NodeKind::HashedValueBranch =>
74			size_and_prefix_iterator(size, trie_constants::ALT_HASHING_BRANCH_WITH_MASK, 4),
75	};
76	iter_start
77		.chain(if nibbles.len() % 2 == 1 { Some(nibbles[0]) } else { None })
78		.chain(nibbles[nibbles.len() % 2..].chunks(2).map(|ch| ch[0] << 4 | ch[1]))
79}
80
81use trie_root::Value as TrieStreamValue;
82impl trie_root::TrieStream for TrieStream {
83	fn new() -> Self {
84		Self { buffer: Vec::new() }
85	}
86
87	fn append_empty_data(&mut self) {
88		self.buffer.push(trie_constants::EMPTY_TRIE);
89	}
90
91	fn append_leaf(&mut self, key: &[u8], value: TrieStreamValue) {
92		let kind = match &value {
93			TrieStreamValue::Inline(..) => NodeKind::Leaf,
94			TrieStreamValue::Node(..) => NodeKind::HashedValueLeaf,
95		};
96		self.buffer.extend(fuse_nibbles_node(key, kind));
97		match &value {
98			TrieStreamValue::Inline(value) => {
99				Compact(value.len() as u32).encode_to(&mut self.buffer);
100				self.buffer.extend_from_slice(value);
101			},
102			TrieStreamValue::Node(hash) => {
103				self.buffer.extend_from_slice(hash.as_slice());
104			},
105		};
106	}
107
108	fn begin_branch(
109		&mut self,
110		maybe_partial: Option<&[u8]>,
111		maybe_value: Option<TrieStreamValue>,
112		has_children: impl Iterator<Item = bool>,
113	) {
114		if let Some(partial) = maybe_partial {
115			let kind = match &maybe_value {
116				None => NodeKind::BranchNoValue,
117				Some(TrieStreamValue::Inline(..)) => NodeKind::BranchWithValue,
118				Some(TrieStreamValue::Node(..)) => NodeKind::HashedValueBranch,
119			};
120
121			self.buffer.extend(fuse_nibbles_node(partial, kind));
122			let bm = branch_node_bit_mask(has_children);
123			self.buffer.extend([bm.0, bm.1].iter());
124		} else {
125			unreachable!("trie stream codec only for no extension trie");
126		}
127		match maybe_value {
128			None => (),
129			Some(TrieStreamValue::Inline(value)) => {
130				Compact(value.len() as u32).encode_to(&mut self.buffer);
131				self.buffer.extend_from_slice(value);
132			},
133			Some(TrieStreamValue::Node(hash)) => {
134				self.buffer.extend_from_slice(hash.as_slice());
135			},
136		}
137	}
138
139	fn append_extension(&mut self, _key: &[u8]) {
140		debug_assert!(false, "trie stream codec only for no extension trie");
141	}
142
143	fn append_substream<H: Hasher>(&mut self, other: Self) {
144		let data = other.out();
145		match data.len() {
146			0..=31 => data.encode_to(&mut self.buffer),
147			_ => H::hash(&data).as_ref().encode_to(&mut self.buffer),
148		}
149	}
150
151	fn out(self) -> Vec<u8> {
152		self.buffer
153	}
154}
155
156/// Helper struct for trie node decoder. This implements `codec::Input` on a byte slice, while
157/// tracking the absolute position. This is similar to `std::io::Cursor` but does not implement
158/// `Read` and `io` is not in `sp-std`.
159struct ByteSliceInput<'a> {
160	data: &'a [u8],
161	offset: usize,
162}
163
164impl<'a> ByteSliceInput<'a> {
165	fn new(data: &'a [u8]) -> Self {
166		ByteSliceInput { data, offset: 0 }
167	}
168
169	fn take(&mut self, count: usize) -> Result<Range<usize>, codec::Error> {
170		if self.offset + count > self.data.len() {
171			return Err("out of data".into())
172		}
173
174		let range = self.offset..(self.offset + count);
175		self.offset += count;
176		Ok(range)
177	}
178}
179
180impl<'a> Input for ByteSliceInput<'a> {
181	fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
182		Ok(Some(self.data.len().saturating_sub(self.offset)))
183	}
184
185	fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> {
186		let range = self.take(into.len())?;
187		into.copy_from_slice(&self.data[range]);
188		Ok(())
189	}
190
191	fn read_byte(&mut self) -> Result<u8, codec::Error> {
192		if self.offset + 1 > self.data.len() {
193			return Err("out of data".into())
194		}
195
196		let byte = self.data[self.offset];
197		self.offset += 1;
198		Ok(byte)
199	}
200}
201
202/// Concrete implementation of a [`NodeCodecT`] with SCALE encoding.
203///
204/// It is generic over `H` the [`Hasher`].
205#[derive(Default, Clone)]
206pub struct NodeCodec<H>(PhantomData<H>);
207
208impl<H> NodeCodecT for NodeCodec<H>
209where
210	H: Hasher,
211{
212	const ESCAPE_HEADER: Option<u8> = Some(trie_constants::ESCAPE_COMPACT_HEADER);
213	type Error = Error<H::Out>;
214	type HashOut = H::Out;
215
216	fn hashed_null_node() -> <H as Hasher>::Out {
217		H::hash(<Self as NodeCodecT>::empty_node())
218	}
219
220	fn decode_plan(data: &[u8]) -> Result<NodePlan, Self::Error> {
221		let mut input = ByteSliceInput::new(data);
222
223		let header = NodeHeader::decode(&mut input)?;
224		let contains_hash = header.contains_hash_of_value();
225
226		let branch_has_value = if let NodeHeader::Branch(has_value, _) = &header {
227			*has_value
228		} else {
229			// hashed_value_branch
230			true
231		};
232
233		match header {
234			NodeHeader::Null => Ok(NodePlan::Empty),
235			NodeHeader::HashedValueBranch(nibble_count) | NodeHeader::Branch(_, nibble_count) => {
236				let padding = nibble_count % nibble_ops::NIBBLE_PER_BYTE != 0;
237				// check that the padding is valid (if any)
238				if padding && nibble_ops::pad_left(data[input.offset]) != 0 {
239					return Err(Error::BadFormat)
240				}
241				let partial = input.take(
242					(nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) /
243						nibble_ops::NIBBLE_PER_BYTE,
244				)?;
245				let partial_padding = nibble_ops::number_padding(nibble_count);
246				let bitmap_range = input.take(BITMAP_LENGTH)?;
247				let bitmap = Bitmap::decode(&data[bitmap_range])?;
248				let value = if branch_has_value {
249					Some(if contains_hash {
250						ValuePlan::Node(input.take(H::LENGTH)?)
251					} else {
252						let count = <Compact<u32>>::decode(&mut input)?.0 as usize;
253						ValuePlan::Inline(input.take(count)?)
254					})
255				} else {
256					None
257				};
258				let mut children = [
259					None, None, None, None, None, None, None, None, None, None, None, None, None,
260					None, None, None,
261				];
262				for i in 0..nibble_ops::NIBBLE_LENGTH {
263					if bitmap.value_at(i) {
264						let count = <Compact<u32>>::decode(&mut input)?.0 as usize;
265						let range = input.take(count)?;
266						children[i] = Some(if count == H::LENGTH {
267							NodeHandlePlan::Hash(range)
268						} else {
269							NodeHandlePlan::Inline(range)
270						});
271					}
272				}
273				Ok(NodePlan::NibbledBranch {
274					partial: NibbleSlicePlan::new(partial, partial_padding),
275					value,
276					children,
277				})
278			},
279			NodeHeader::HashedValueLeaf(nibble_count) | NodeHeader::Leaf(nibble_count) => {
280				let padding = nibble_count % nibble_ops::NIBBLE_PER_BYTE != 0;
281				// check that the padding is valid (if any)
282				if padding && nibble_ops::pad_left(data[input.offset]) != 0 {
283					return Err(Error::BadFormat)
284				}
285				let partial = input.take(
286					(nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) /
287						nibble_ops::NIBBLE_PER_BYTE,
288				)?;
289				let partial_padding = nibble_ops::number_padding(nibble_count);
290				let value = if contains_hash {
291					ValuePlan::Node(input.take(H::LENGTH)?)
292				} else {
293					let count = <Compact<u32>>::decode(&mut input)?.0 as usize;
294					ValuePlan::Inline(input.take(count)?)
295				};
296
297				Ok(NodePlan::Leaf {
298					partial: NibbleSlicePlan::new(partial, partial_padding),
299					value,
300				})
301			},
302		}
303	}
304
305	fn is_empty_node(data: &[u8]) -> bool {
306		data == <Self as NodeCodecT>::empty_node()
307	}
308
309	fn empty_node() -> &'static [u8] {
310		&[trie_constants::EMPTY_TRIE]
311	}
312
313	fn leaf_node(partial: impl Iterator<Item = u8>, number_nibble: usize, value: Value) -> Vec<u8> {
314		let contains_hash = matches!(&value, Value::Node(..));
315		let mut output = if contains_hash {
316			partial_from_iterator_encode(partial, number_nibble, NodeKind::HashedValueLeaf)
317		} else {
318			partial_from_iterator_encode(partial, number_nibble, NodeKind::Leaf)
319		};
320		match value {
321			Value::Inline(value) => {
322				Compact(value.len() as u32).encode_to(&mut output);
323				output.extend_from_slice(value);
324			},
325			Value::Node(hash) => {
326				debug_assert!(hash.len() == H::LENGTH);
327				output.extend_from_slice(hash);
328			},
329		}
330		output
331	}
332
333	fn extension_node(
334		_partial: impl Iterator<Item = u8>,
335		_nbnibble: usize,
336		_child: ChildReference<<H as Hasher>::Out>,
337	) -> Vec<u8> {
338		unreachable!("No extension codec.")
339	}
340
341	fn branch_node(
342		_children: impl Iterator<Item = impl Borrow<Option<ChildReference<<H as Hasher>::Out>>>>,
343		_maybe_value: Option<Value>,
344	) -> Vec<u8> {
345		unreachable!("No extension codec.")
346	}
347
348	fn branch_node_nibbled(
349		partial: impl Iterator<Item = u8>,
350		number_nibble: usize,
351		children: impl Iterator<Item = impl Borrow<Option<ChildReference<<H as Hasher>::Out>>>>,
352		value: Option<Value>,
353	) -> Vec<u8> {
354		let contains_hash = matches!(&value, Some(Value::Node(..)));
355		let mut output = match (&value, contains_hash) {
356			(&None, _) =>
357				partial_from_iterator_encode(partial, number_nibble, NodeKind::BranchNoValue),
358			(_, false) =>
359				partial_from_iterator_encode(partial, number_nibble, NodeKind::BranchWithValue),
360			(_, true) =>
361				partial_from_iterator_encode(partial, number_nibble, NodeKind::HashedValueBranch),
362		};
363
364		let bitmap_index = output.len();
365		let mut bitmap: [u8; BITMAP_LENGTH] = [0; BITMAP_LENGTH];
366		(0..BITMAP_LENGTH).for_each(|_| output.push(0));
367		match value {
368			Some(Value::Inline(value)) => {
369				Compact(value.len() as u32).encode_to(&mut output);
370				output.extend_from_slice(value);
371			},
372			Some(Value::Node(hash)) => {
373				debug_assert!(hash.len() == H::LENGTH);
374				output.extend_from_slice(hash);
375			},
376			None => (),
377		}
378		Bitmap::encode(
379			children.map(|maybe_child| match maybe_child.borrow() {
380				Some(ChildReference::Hash(h)) => {
381					h.as_ref().encode_to(&mut output);
382					true
383				},
384				&Some(ChildReference::Inline(inline_data, len)) => {
385					inline_data.as_ref()[..len].encode_to(&mut output);
386					true
387				},
388				None => false,
389			}),
390			bitmap.as_mut(),
391		);
392		output[bitmap_index..bitmap_index + BITMAP_LENGTH]
393			.copy_from_slice(&bitmap[..BITMAP_LENGTH]);
394		output
395	}
396}
397
398// utils
399
400/// Encode and allocate node type header (type and size), and partial value.
401/// It uses an iterator over encoded partial bytes as input.
402fn partial_from_iterator_encode<I: Iterator<Item = u8>>(
403	partial: I,
404	nibble_count: usize,
405	node_kind: NodeKind,
406) -> Vec<u8> {
407	let mut output = Vec::with_capacity(4 + (nibble_count / nibble_ops::NIBBLE_PER_BYTE));
408	match node_kind {
409		NodeKind::Leaf => NodeHeader::Leaf(nibble_count).encode_to(&mut output),
410		NodeKind::BranchWithValue => NodeHeader::Branch(true, nibble_count).encode_to(&mut output),
411		NodeKind::BranchNoValue => NodeHeader::Branch(false, nibble_count).encode_to(&mut output),
412		NodeKind::HashedValueLeaf =>
413			NodeHeader::HashedValueLeaf(nibble_count).encode_to(&mut output),
414		NodeKind::HashedValueBranch =>
415			NodeHeader::HashedValueBranch(nibble_count).encode_to(&mut output),
416	};
417	output.extend(partial);
418	output
419}
420
421const BITMAP_LENGTH: usize = 2;
422
423/// Radix 16 trie, bitmap encoding implementation,
424/// it contains children mapping information for a branch
425/// (children presence only), it encodes into
426/// a compact bitmap encoding representation.
427pub(crate) struct Bitmap(u16);
428
429impl Bitmap {
430	pub fn decode(data: &[u8]) -> Result<Self, codec::Error> {
431		let value = u16::decode(&mut &data[..])?;
432		if value == 0 {
433			Err("Bitmap without a child.".into())
434		} else {
435			Ok(Bitmap(value))
436		}
437	}
438
439	pub fn value_at(&self, i: usize) -> bool {
440		self.0 & (1u16 << i) != 0
441	}
442
443	pub fn encode<I: Iterator<Item = bool>>(has_children: I, dest: &mut [u8]) {
444		let mut bitmap: u16 = 0;
445		let mut cursor: u16 = 1;
446		for v in has_children {
447			if v {
448				bitmap |= cursor
449			}
450			cursor <<= 1;
451		}
452		dest[0] = (bitmap % 256) as u8;
453		dest[1] = (bitmap / 256) as u8;
454	}
455}
456
457/// substrate trie layout
458pub struct LayoutV0<H>(PhantomData<H>);
459
460/// substrate trie layout, with external value nodes.
461pub struct LayoutV1<H>(PhantomData<H>);
462
463impl<H> TrieLayout for LayoutV0<H>
464where
465	H: Hasher + core::fmt::Debug,
466{
467	const USE_EXTENSION: bool = false;
468	const ALLOW_EMPTY: bool = true;
469	const MAX_INLINE_VALUE: Option<u32> = None;
470
471	type Hash = H;
472	type Codec = NodeCodec<Self::Hash>;
473}
474
475impl<H> TrieConfiguration for LayoutV0<H>
476where
477	H: Hasher + core::fmt::Debug,
478{
479	fn trie_root<I, A, B>(input: I) -> <Self::Hash as Hasher>::Out
480	where
481		I: IntoIterator<Item = (A, B)>,
482		A: AsRef<[u8]> + Ord,
483		B: AsRef<[u8]>,
484	{
485		trie_root::trie_root_no_extension::<H, TrieStream, _, _, _>(input, Self::MAX_INLINE_VALUE)
486	}
487
488	fn trie_root_unhashed<I, A, B>(input: I) -> Vec<u8>
489	where
490		I: IntoIterator<Item = (A, B)>,
491		A: AsRef<[u8]> + Ord,
492		B: AsRef<[u8]>,
493	{
494		trie_root::unhashed_trie_no_extension::<H, TrieStream, _, _, _>(
495			input,
496			Self::MAX_INLINE_VALUE,
497		)
498	}
499
500	fn encode_index(input: u32) -> Vec<u8> {
501		codec::Encode::encode(&codec::Compact(input))
502	}
503}
504
505impl<H> TrieLayout for LayoutV1<H>
506where
507	H: Hasher + core::fmt::Debug,
508{
509	const USE_EXTENSION: bool = false;
510	const ALLOW_EMPTY: bool = true;
511	const MAX_INLINE_VALUE: Option<u32> = Some(TRIE_VALUE_NODE_THRESHOLD);
512
513	type Hash = H;
514	type Codec = NodeCodec<Self::Hash>;
515}
516
517impl<H> TrieConfiguration for LayoutV1<H>
518where
519	H: Hasher + core::fmt::Debug,
520{
521	fn trie_root<I, A, B>(input: I) -> <Self::Hash as Hasher>::Out
522	where
523		I: IntoIterator<Item = (A, B)>,
524		A: AsRef<[u8]> + Ord,
525		B: AsRef<[u8]>,
526	{
527		trie_root::trie_root_no_extension::<H, TrieStream, _, _, _>(input, Self::MAX_INLINE_VALUE)
528	}
529
530	fn trie_root_unhashed<I, A, B>(input: I) -> Vec<u8>
531	where
532		I: IntoIterator<Item = (A, B)>,
533		A: AsRef<[u8]> + Ord,
534		B: AsRef<[u8]>,
535	{
536		trie_root::unhashed_trie_no_extension::<H, TrieStream, _, _, _>(
537			input,
538			Self::MAX_INLINE_VALUE,
539		)
540	}
541
542	fn encode_index(input: u32) -> Vec<u8> {
543		codec::Encode::encode(&codec::Compact(input))
544	}
545}
546
547/// A node header
548#[derive(Copy, Clone, PartialEq, Eq, Debug)]
549pub(crate) enum NodeHeader {
550	Null,
551	// contains wether there is a value and nibble count
552	Branch(bool, usize),
553	// contains nibble count
554	Leaf(usize),
555	// contains nibble count.
556	HashedValueBranch(usize),
557	// contains nibble count.
558	HashedValueLeaf(usize),
559}
560
561impl NodeHeader {
562	pub(crate) fn contains_hash_of_value(&self) -> bool {
563		matches!(self, NodeHeader::HashedValueBranch(_) | NodeHeader::HashedValueLeaf(_))
564	}
565}
566
567/// NodeHeader without content
568pub(crate) enum NodeKind {
569	Leaf,
570	BranchNoValue,
571	BranchWithValue,
572	HashedValueLeaf,
573	HashedValueBranch,
574}
575
576impl Encode for NodeHeader {
577	fn encode_to<T: Output + ?Sized>(&self, output: &mut T) {
578		match self {
579			NodeHeader::Null => output.push_byte(trie_constants::EMPTY_TRIE),
580			NodeHeader::Branch(true, nibble_count) =>
581				encode_size_and_prefix(*nibble_count, trie_constants::BRANCH_WITH_MASK, 2, output),
582			NodeHeader::Branch(false, nibble_count) => encode_size_and_prefix(
583				*nibble_count,
584				trie_constants::BRANCH_WITHOUT_MASK,
585				2,
586				output,
587			),
588			NodeHeader::Leaf(nibble_count) =>
589				encode_size_and_prefix(*nibble_count, trie_constants::LEAF_PREFIX_MASK, 2, output),
590			NodeHeader::HashedValueBranch(nibble_count) => encode_size_and_prefix(
591				*nibble_count,
592				trie_constants::ALT_HASHING_BRANCH_WITH_MASK,
593				4,
594				output,
595			),
596			NodeHeader::HashedValueLeaf(nibble_count) => encode_size_and_prefix(
597				*nibble_count,
598				trie_constants::ALT_HASHING_LEAF_PREFIX_MASK,
599				3,
600				output,
601			),
602		}
603	}
604}
605
606impl codec::EncodeLike for NodeHeader {}
607
608impl Decode for NodeHeader {
609	fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> {
610		let i = input.read_byte()?;
611		if i == trie_constants::EMPTY_TRIE {
612			return Ok(NodeHeader::Null)
613		}
614		match i & (0b11 << 6) {
615			trie_constants::LEAF_PREFIX_MASK => Ok(NodeHeader::Leaf(decode_size(i, input, 2)?)),
616			trie_constants::BRANCH_WITH_MASK =>
617				Ok(NodeHeader::Branch(true, decode_size(i, input, 2)?)),
618			trie_constants::BRANCH_WITHOUT_MASK =>
619				Ok(NodeHeader::Branch(false, decode_size(i, input, 2)?)),
620			trie_constants::EMPTY_TRIE => {
621				if i & (0b111 << 5) == trie_constants::ALT_HASHING_LEAF_PREFIX_MASK {
622					Ok(NodeHeader::HashedValueLeaf(decode_size(i, input, 3)?))
623				} else if i & (0b1111 << 4) == trie_constants::ALT_HASHING_BRANCH_WITH_MASK {
624					Ok(NodeHeader::HashedValueBranch(decode_size(i, input, 4)?))
625				} else {
626					// do not allow any special encoding
627					Err("Unallowed encoding".into())
628				}
629			},
630			_ => unreachable!(),
631		}
632	}
633}
634
635/// Returns an iterator over encoded bytes for node header and size.
636/// Size encoding allows unlimited, length inefficient, representation, but
637/// is bounded to 16 bit maximum value to avoid possible DOS.
638pub(crate) fn size_and_prefix_iterator(
639	size: usize,
640	prefix: u8,
641	prefix_mask: usize,
642) -> impl Iterator<Item = u8> {
643	let max_value = 255u8 >> prefix_mask;
644	let l1 = core::cmp::min((max_value as usize).saturating_sub(1), size);
645	let (first_byte, mut rem) = if size == l1 {
646		(once(prefix + l1 as u8), 0)
647	} else {
648		(once(prefix + max_value as u8), size - l1)
649	};
650	let next_bytes = move || {
651		if rem > 0 {
652			if rem < 256 {
653				let result = rem - 1;
654				rem = 0;
655				Some(result as u8)
656			} else {
657				rem = rem.saturating_sub(255);
658				Some(255)
659			}
660		} else {
661			None
662		}
663	};
664	first_byte.chain(core::iter::from_fn(next_bytes))
665}
666
667/// Encodes size and prefix to a stream output.
668fn encode_size_and_prefix<W>(size: usize, prefix: u8, prefix_mask: usize, out: &mut W)
669where
670	W: Output + ?Sized,
671{
672	for b in size_and_prefix_iterator(size, prefix, prefix_mask) {
673		out.push_byte(b)
674	}
675}
676
677/// Decode size only from stream input and header byte.
678fn decode_size(
679	first: u8,
680	input: &mut impl Input,
681	prefix_mask: usize,
682) -> Result<usize, codec::Error> {
683	let max_value = 255u8 >> prefix_mask;
684	let mut result = (first & max_value) as usize;
685	if result < max_value as usize {
686		return Ok(result)
687	}
688	result -= 1;
689	loop {
690		let n = input.read_byte()? as usize;
691		if n < 255 {
692			return Ok(result + n + 1)
693		}
694		result += 255;
695	}
696}
697
698/// Error type used for trie related errors.
699#[derive(Debug, PartialEq, Eq, Clone)]
700pub enum Error<H> {
701	BadFormat,
702	Decode(codec::Error),
703	InvalidRecording(Vec<u8>, bool),
704	TrieError(Box<trie_db::TrieError<H, Self>>),
705}
706
707impl<H> core::fmt::Display for Error<H> {
708	fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
709		fmt.write_str("Error")
710	}
711}
712
713impl<H> std::error::Error for Error<H> where H: core::fmt::Debug {}
714
715impl<H> From<codec::Error> for Error<H> {
716	fn from(x: codec::Error) -> Self {
717		Error::Decode(x)
718	}
719}
720
721impl<H> From<Box<trie_db::TrieError<H, Self>>> for Error<H> {
722	fn from(x: Box<trie_db::TrieError<H, Self>>) -> Self {
723		Error::TrieError(x)
724	}
725}