diem_types/nibble/nibble_path/
mod.rs1#[cfg(test)]
8mod nibble_path_test;
9
10use crate::nibble::{Nibble, ROOT_NIBBLE_HEIGHT};
11use mirai_annotations::*;
12#[cfg(any(test, feature = "fuzzing"))]
13use proptest::{collection::vec, prelude::*};
14use serde::{Deserialize, Serialize};
15use std::{fmt, iter::FromIterator};
16
17#[derive(Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
19pub struct NibblePath {
20 num_nibbles: usize,
25 bytes: Vec<u8>,
28 }
30
31impl fmt::Debug for NibblePath {
34 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35 self.nibbles().try_for_each(|x| write!(f, "{:x}", x))
36 }
37}
38
39impl FromIterator<Nibble> for NibblePath {
41 fn from_iter<I: IntoIterator<Item = Nibble>>(iter: I) -> Self {
42 let mut nibble_path = NibblePath::new(vec![]);
43 for nibble in iter {
44 nibble_path.push(nibble);
45 }
46 nibble_path
47 }
48}
49
50#[cfg(any(test, feature = "fuzzing"))]
51impl Arbitrary for NibblePath {
52 type Parameters = ();
53 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
54 arb_nibble_path().boxed()
55 }
56 type Strategy = BoxedStrategy<Self>;
57}
58
59#[cfg(any(test, feature = "fuzzing"))]
60prop_compose! {
61 fn arb_nibble_path()(
62 mut bytes in vec(any::<u8>(), 0..=ROOT_NIBBLE_HEIGHT/2),
63 is_odd in any::<bool>()
64 ) -> NibblePath {
65 if let Some(last_byte) = bytes.last_mut() {
66 if is_odd {
67 *last_byte &= 0xf0;
68 return NibblePath::new_odd(bytes);
69 }
70 }
71 NibblePath::new(bytes)
72 }
73}
74
75#[cfg(any(test, feature = "fuzzing"))]
76prop_compose! {
77 fn arb_internal_nibble_path()(
78 nibble_path in arb_nibble_path().prop_filter(
79 "Filter out leaf paths.",
80 |p| p.num_nibbles() < ROOT_NIBBLE_HEIGHT,
81 )
82 ) -> NibblePath {
83 nibble_path
84 }
85}
86
87impl NibblePath {
88 pub fn new(bytes: Vec<u8>) -> Self {
90 checked_precondition!(bytes.len() <= ROOT_NIBBLE_HEIGHT / 2);
91 let num_nibbles = bytes.len() * 2;
92 NibblePath { num_nibbles, bytes }
93 }
94
95 pub fn new_odd(bytes: Vec<u8>) -> Self {
97 checked_precondition!(bytes.len() <= ROOT_NIBBLE_HEIGHT / 2);
98 assert_eq!(
99 bytes.last().expect("Should have odd number of nibbles.") & 0x0f,
100 0,
101 "Last nibble must be 0."
102 );
103 let num_nibbles = bytes.len() * 2 - 1;
104 NibblePath { num_nibbles, bytes }
105 }
106
107 pub fn push(&mut self, nibble: Nibble) {
109 assert!(ROOT_NIBBLE_HEIGHT > self.num_nibbles);
110 if self.num_nibbles % 2 == 0 {
111 self.bytes.push(u8::from(nibble) << 4);
112 } else {
113 self.bytes[self.num_nibbles / 2] |= u8::from(nibble);
114 }
115 self.num_nibbles += 1;
116 }
117
118 pub fn pop(&mut self) -> Option<Nibble> {
120 let poped_nibble = if self.num_nibbles % 2 == 0 {
121 self.bytes.last_mut().map(|last_byte| {
122 let nibble = *last_byte & 0x0f;
123 *last_byte &= 0xf0;
124 Nibble::from(nibble)
125 })
126 } else {
127 self.bytes.pop().map(|byte| Nibble::from(byte >> 4))
128 };
129 if poped_nibble.is_some() {
130 self.num_nibbles -= 1;
131 }
132 poped_nibble
133 }
134
135 pub fn last(&self) -> Option<Nibble> {
137 let last_byte_option = self.bytes.last();
138 if self.num_nibbles % 2 == 0 {
139 last_byte_option.map(|last_byte| Nibble::from(*last_byte & 0x0f))
140 } else {
141 let last_byte = last_byte_option.expect("Last byte must exist if num_nibbles is odd.");
142 Some(Nibble::from(*last_byte >> 4))
143 }
144 }
145
146 fn get_bit(&self, i: usize) -> bool {
148 assert!(i < self.num_nibbles * 4);
149 let pos = i / 8;
150 let bit = 7 - i % 8;
151 ((self.bytes[pos] >> bit) & 1) != 0
152 }
153
154 pub fn get_nibble(&self, i: usize) -> Nibble {
156 assert!(i < self.num_nibbles);
157 Nibble::from((self.bytes[i / 2] >> (if i % 2 == 1 { 0 } else { 4 })) & 0xf)
158 }
159
160 pub fn bits(&self) -> BitIterator {
162 assume!(self.num_nibbles <= ROOT_NIBBLE_HEIGHT); BitIterator {
164 nibble_path: self,
165 pos: (0..self.num_nibbles * 4),
166 }
167 }
168
169 pub fn nibbles(&self) -> NibbleIterator {
171 assume!(self.num_nibbles <= ROOT_NIBBLE_HEIGHT); NibbleIterator::new(self, 0, self.num_nibbles)
173 }
174
175 pub fn num_nibbles(&self) -> usize {
177 self.num_nibbles
178 }
179
180 pub fn is_empty(&self) -> bool {
182 self.num_nibbles() == 0
183 }
184
185 pub fn bytes(&self) -> &[u8] {
187 &self.bytes
188 }
189}
190
191pub trait Peekable: Iterator {
192 fn peek(&self) -> Option<Self::Item>;
194}
195
196pub struct BitIterator<'a> {
198 nibble_path: &'a NibblePath,
199 pos: std::ops::Range<usize>,
200}
201
202impl<'a> Peekable for BitIterator<'a> {
203 fn peek(&self) -> Option<Self::Item> {
205 if self.pos.start < self.pos.end {
206 Some(self.nibble_path.get_bit(self.pos.start))
207 } else {
208 None
209 }
210 }
211}
212
213impl<'a> Iterator for BitIterator<'a> {
215 type Item = bool;
216 fn next(&mut self) -> Option<Self::Item> {
217 self.pos.next().map(|i| self.nibble_path.get_bit(i))
218 }
219}
220
221impl<'a> DoubleEndedIterator for BitIterator<'a> {
223 fn next_back(&mut self) -> Option<Self::Item> {
224 self.pos.next_back().map(|i| self.nibble_path.get_bit(i))
225 }
226}
227
228#[derive(Debug)]
230pub struct NibbleIterator<'a> {
231 nibble_path: &'a NibblePath,
233
234 pos: std::ops::Range<usize>,
237
238 start: usize,
242 }
246
247impl<'a> Iterator for NibbleIterator<'a> {
249 type Item = Nibble;
250 fn next(&mut self) -> Option<Self::Item> {
251 self.pos.next().map(|i| self.nibble_path.get_nibble(i))
252 }
253}
254
255impl<'a> Peekable for NibbleIterator<'a> {
256 fn peek(&self) -> Option<Self::Item> {
258 if self.pos.start < self.pos.end {
259 Some(self.nibble_path.get_nibble(self.pos.start))
260 } else {
261 None
262 }
263 }
264}
265
266impl<'a> NibbleIterator<'a> {
267 fn new(nibble_path: &'a NibblePath, start: usize, end: usize) -> Self {
268 precondition!(start <= end);
269 precondition!(start <= ROOT_NIBBLE_HEIGHT);
270 precondition!(end <= ROOT_NIBBLE_HEIGHT);
271 Self {
272 nibble_path,
273 pos: (start..end),
274 start,
275 }
276 }
277
278 pub fn visited_nibbles(&self) -> NibbleIterator<'a> {
280 assume!(self.start <= self.pos.start); assume!(self.pos.start <= ROOT_NIBBLE_HEIGHT); Self::new(self.nibble_path, self.start, self.pos.start)
283 }
284
285 pub fn remaining_nibbles(&self) -> NibbleIterator<'a> {
287 assume!(self.pos.start <= self.pos.end); assume!(self.pos.end <= ROOT_NIBBLE_HEIGHT); Self::new(self.nibble_path, self.pos.start, self.pos.end)
290 }
291
292 pub fn bits(&self) -> BitIterator<'a> {
294 assume!(self.pos.start <= self.pos.end); assume!(self.pos.end <= ROOT_NIBBLE_HEIGHT); BitIterator {
297 nibble_path: self.nibble_path,
298 pos: (self.pos.start * 4..self.pos.end * 4),
299 }
300 }
301
302 pub fn get_nibble_path(&self) -> NibblePath {
305 self.visited_nibbles()
306 .chain(self.remaining_nibbles())
307 .collect()
308 }
309
310 pub fn num_nibbles(&self) -> usize {
312 assume!(self.start <= self.pos.end); self.pos.end - self.start
314 }
315
316 pub fn is_finished(&self) -> bool {
318 self.peek().is_none()
319 }
320}
321
322pub fn skip_common_prefix<I1, I2>(x: &mut I1, y: &mut I2) -> usize
325where
326 I1: Iterator + Peekable,
327 I2: Iterator + Peekable,
328 <I1 as Iterator>::Item: std::cmp::PartialEq<<I2 as Iterator>::Item>,
329{
330 let mut count = 0;
331 loop {
332 let x_peek = x.peek();
333 let y_peek = y.peek();
334 if x_peek.is_none()
335 || y_peek.is_none()
336 || x_peek.expect("cannot be none") != y_peek.expect("cannot be none")
337 {
338 break;
339 }
340 count += 1;
341 x.next();
342 y.next();
343 }
344 count
345}