diem_jellyfish_merkle/nibble_path/
mod.rs1#[cfg(test)]
13mod nibble_path_test;
14
15use crate::ROOT_NIBBLE_HEIGHT;
16use diem_nibble::Nibble;
17use mirai_annotations::*;
18#[cfg(any(test, feature = "fuzzing"))]
19use proptest::{collection::vec, prelude::*};
20use serde::{Deserialize, Serialize};
21use std::{fmt, iter::FromIterator};
22
23#[derive(
25 Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize,
26)]
27pub struct NibblePath {
28 num_nibbles: usize,
33 bytes: Vec<u8>,
37 }
39
40impl fmt::Debug for NibblePath {
43 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
44 self.nibbles().try_for_each(|x| write!(f, "{:x}", x))
45 }
46}
47
48impl FromIterator<Nibble> for NibblePath {
51 fn from_iter<I: IntoIterator<Item = Nibble>>(iter: I) -> Self {
52 let mut nibble_path = NibblePath::new(vec![]);
53 for nibble in iter {
54 nibble_path.push(nibble);
55 }
56 nibble_path
57 }
58}
59
60#[cfg(any(test, feature = "fuzzing"))]
61impl Arbitrary for NibblePath {
62 type Parameters = ();
63 type Strategy = BoxedStrategy<Self>;
64
65 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
66 arb_nibble_path().boxed()
67 }
68}
69
70#[cfg(any(test, feature = "fuzzing"))]
71prop_compose! {
72 fn arb_nibble_path()(
73 mut bytes in vec(any::<u8>(), 0..=ROOT_NIBBLE_HEIGHT/2),
74 is_odd in any::<bool>()
75 ) -> NibblePath {
76 if let Some(last_byte) = bytes.last_mut() {
77 if is_odd {
78 *last_byte &= 0xf0;
79 return NibblePath::new_odd(bytes);
80 }
81 }
82 NibblePath::new(bytes)
83 }
84}
85
86#[cfg(any(test, feature = "fuzzing"))]
87prop_compose! {
88 fn arb_internal_nibble_path()(
89 nibble_path in arb_nibble_path().prop_filter(
90 "Filter out leaf paths.",
91 |p| p.num_nibbles() < ROOT_NIBBLE_HEIGHT,
92 )
93 ) -> NibblePath {
94 nibble_path
95 }
96}
97
98impl NibblePath {
99 pub fn new(bytes: Vec<u8>) -> Self {
102 checked_precondition!(bytes.len() <= ROOT_NIBBLE_HEIGHT / 2);
103 let num_nibbles = bytes.len() * 2;
104 NibblePath { bytes, num_nibbles }
105 }
106
107 pub fn new_odd(bytes: Vec<u8>) -> Self {
109 checked_precondition!(bytes.len() <= ROOT_NIBBLE_HEIGHT / 2);
110 assert_eq!(
111 bytes.last().expect("Should have odd number of nibbles.") & 0x0f,
112 0,
113 "Last nibble must be 0."
114 );
115 let num_nibbles = bytes.len() * 2 - 1;
116 NibblePath { bytes, num_nibbles }
117 }
118
119 pub fn push(&mut self, nibble: Nibble) {
121 assert!(ROOT_NIBBLE_HEIGHT > self.num_nibbles);
122 if self.num_nibbles % 2 == 0 {
123 self.bytes.push(u8::from(nibble) << 4);
124 } else {
125 self.bytes[self.num_nibbles / 2] |= u8::from(nibble);
126 }
127 self.num_nibbles += 1;
128 }
129
130 pub fn pop(&mut self) -> Option<Nibble> {
132 let poped_nibble = if self.num_nibbles % 2 == 0 {
133 self.bytes.last_mut().map(|last_byte| {
134 let nibble = *last_byte & 0x0f;
135 *last_byte &= 0xf0;
136 Nibble::from(nibble)
137 })
138 } else {
139 self.bytes.pop().map(|byte| Nibble::from(byte >> 4))
140 };
141 if poped_nibble.is_some() {
142 self.num_nibbles -= 1;
143 }
144 poped_nibble
145 }
146
147 pub fn last(&self) -> Option<Nibble> {
149 let last_byte_option = self.bytes.last();
150 if self.num_nibbles % 2 == 0 {
151 last_byte_option.map(|last_byte| Nibble::from(*last_byte & 0x0f))
152 } else {
153 let last_byte = last_byte_option
154 .expect("Last byte must exist if num_nibbles is odd.");
155 Some(Nibble::from(*last_byte >> 4))
156 }
157 }
158
159 fn get_bit(&self, i: usize) -> bool {
161 assert!(i / 4 < self.num_nibbles);
162 let pos = i / 8;
163 let bit = 7 - i % 8;
164 ((self.bytes[pos] >> bit) & 1) != 0
165 }
166
167 fn get_nibble(&self, i: usize) -> Nibble {
169 assert!(i < self.num_nibbles);
170 Nibble::from(
171 (self.bytes[i / 2] >> (if i % 2 == 1 { 0 } else { 4 })) & 0xf,
172 )
173 }
174
175 pub fn bits(&self) -> BitIterator<'_> {
177 assume!(self.num_nibbles <= ROOT_NIBBLE_HEIGHT); BitIterator {
179 nibble_path: self,
180 pos: (0..self.num_nibbles * 4),
181 }
182 }
183
184 pub fn nibbles(&self) -> NibbleIterator<'_> {
186 assume!(self.num_nibbles <= ROOT_NIBBLE_HEIGHT); NibbleIterator::new(self, 0, self.num_nibbles)
188 }
189
190 pub fn num_nibbles(&self) -> usize { self.num_nibbles }
192
193 pub fn bytes(&self) -> &[u8] { &self.bytes }
195}
196
197pub trait Peekable: Iterator {
198 fn peek(&self) -> Option<Self::Item>;
200}
201
202pub struct BitIterator<'a> {
204 nibble_path: &'a NibblePath,
205 pos: std::ops::Range<usize>,
206}
207
208impl<'a> Peekable for BitIterator<'a> {
209 fn peek(&self) -> Option<Self::Item> {
211 if self.pos.start < self.pos.end {
212 Some(self.nibble_path.get_bit(self.pos.start))
213 } else {
214 None
215 }
216 }
217}
218
219impl<'a> Iterator for BitIterator<'a> {
221 type Item = bool;
222
223 fn next(&mut self) -> Option<Self::Item> {
224 self.pos.next().map(|i| self.nibble_path.get_bit(i))
225 }
226}
227
228impl<'a> DoubleEndedIterator for BitIterator<'a> {
230 fn next_back(&mut self) -> Option<Self::Item> {
231 self.pos.next_back().map(|i| self.nibble_path.get_bit(i))
232 }
233}
234
235#[derive(Debug)]
237pub struct NibbleIterator<'a> {
238 nibble_path: &'a NibblePath,
240
241 pos: std::ops::Range<usize>,
244
245 start: usize,
250 }
254
255impl<'a> Iterator for NibbleIterator<'a> {
258 type Item = Nibble;
259
260 fn next(&mut self) -> Option<Self::Item> {
261 self.pos.next().map(|i| self.nibble_path.get_nibble(i))
262 }
263}
264
265impl<'a> Peekable for NibbleIterator<'a> {
266 fn peek(&self) -> Option<Self::Item> {
268 if self.pos.start < self.pos.end {
269 Some(self.nibble_path.get_nibble(self.pos.start))
270 } else {
271 None
272 }
273 }
274}
275
276impl<'a> NibbleIterator<'a> {
277 fn new(nibble_path: &'a NibblePath, start: usize, end: usize) -> Self {
278 precondition!(start <= end);
279 precondition!(start <= ROOT_NIBBLE_HEIGHT);
280 precondition!(end <= ROOT_NIBBLE_HEIGHT);
281 Self {
282 nibble_path,
283 pos: (start..end),
284 start,
285 }
286 }
287
288 pub fn visited_nibbles(&self) -> NibbleIterator<'a> {
290 assume!(self.start <= self.pos.start); assume!(self.pos.start <= ROOT_NIBBLE_HEIGHT); Self::new(self.nibble_path, self.start, self.pos.start)
293 }
294
295 pub fn remaining_nibbles(&self) -> NibbleIterator<'a> {
297 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)
300 }
301
302 pub fn bits(&self) -> BitIterator<'a> {
304 assume!(self.pos.start <= self.pos.end); assume!(self.pos.end <= ROOT_NIBBLE_HEIGHT); BitIterator {
307 nibble_path: self.nibble_path,
308 pos: (self.pos.start * 4..self.pos.end * 4),
309 }
310 }
311
312 pub fn get_nibble_path(&self) -> NibblePath {
315 self.visited_nibbles()
316 .chain(self.remaining_nibbles())
317 .collect()
318 }
319
320 pub fn num_nibbles(&self) -> usize {
322 assume!(self.start <= self.pos.end); self.pos.end - self.start
324 }
325
326 pub fn is_finished(&self) -> bool { self.peek().is_none() }
328}
329
330pub fn skip_common_prefix<'a, 'b, I1: 'a, I2: 'b>(
334 x: &'a mut I1, y: &mut I2,
335) -> usize
336where
337 I1: Iterator + Peekable,
338 I2: Iterator + Peekable,
339 <I1 as Iterator>::Item: std::cmp::PartialEq<<I2 as Iterator>::Item>,
340{
341 let mut count = 0;
342 loop {
343 let x_peek = x.peek();
344 let y_peek = y.peek();
345 if x_peek.is_none()
346 || y_peek.is_none()
347 || x_peek.expect("cannot be none")
348 != y_peek.expect("cannot be none")
349 {
350 break;
351 }
352 count += 1;
353 x.next();
354 y.next();
355 }
356 count
357}