jmt/types/nibble/
nibble_path.rs1use alloc::vec;
8use core::{fmt, iter::FromIterator};
9
10use alloc::vec::Vec;
11use mirai_annotations::*;
12#[cfg(any(test))]
13use proptest::{collection::vec, prelude::*};
14use serde::{Deserialize, Serialize};
15
16use crate::types::nibble::{Nibble, ROOT_NIBBLE_HEIGHT};
17
18#[derive(
20 Clone,
21 Hash,
22 Eq,
23 PartialEq,
24 Ord,
25 PartialOrd,
26 Serialize,
27 Deserialize,
28 borsh::BorshSerialize,
29 borsh::BorshDeserialize,
30)]
31pub struct NibblePath {
32 num_nibbles: usize,
37 bytes: Vec<u8>,
40 }
42
43impl fmt::Debug for NibblePath {
46 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47 self.nibbles().try_for_each(|x| write!(f, "{:x}", x))
48 }
49}
50
51impl FromIterator<Nibble> for NibblePath {
53 fn from_iter<I: IntoIterator<Item = Nibble>>(iter: I) -> Self {
54 let mut nibble_path = NibblePath::new(vec![]);
55 for nibble in iter {
56 nibble_path.push(nibble);
57 }
58 nibble_path
59 }
60}
61
62#[cfg(any(test))]
63impl Arbitrary for NibblePath {
64 type Parameters = ();
65 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
66 arb_nibble_path().boxed()
67 }
68 type Strategy = BoxedStrategy<Self>;
69}
70
71#[cfg(any(test))]
72prop_compose! {
73 fn arb_nibble_path()(
74 mut bytes in vec(any::<u8>(), 0..=ROOT_NIBBLE_HEIGHT/2),
75 is_odd in any::<bool>()
76 ) -> NibblePath {
77 if let Some(last_byte) = bytes.last_mut() {
78 if is_odd {
79 *last_byte &= 0xf0;
80 return NibblePath::new_odd(bytes);
81 }
82 }
83 NibblePath::new(bytes)
84 }
85}
86
87#[cfg(any(test))]
88prop_compose! {
89 pub(crate) fn arb_internal_nibble_path()(
90 nibble_path in arb_nibble_path().prop_filter(
91 "Filter out leaf paths.",
92 |p| p.num_nibbles() < ROOT_NIBBLE_HEIGHT,
93 )
94 ) -> NibblePath {
95 nibble_path
96 }
97}
98
99impl NibblePath {
100 pub(crate) fn new(bytes: Vec<u8>) -> Self {
102 checked_precondition!(bytes.len() <= ROOT_NIBBLE_HEIGHT / 2);
103 let num_nibbles = bytes.len() * 2;
104 NibblePath { num_nibbles, bytes }
105 }
106
107 #[allow(unused)]
111 pub(crate) fn new_odd(bytes: Vec<u8>) -> Self {
112 checked_precondition!(bytes.len() <= ROOT_NIBBLE_HEIGHT / 2);
113 assert_eq!(
114 bytes.last().expect("Should have odd number of nibbles.") & 0x0f,
115 0,
116 "Last nibble must be 0."
117 );
118 let num_nibbles = bytes.len() * 2 - 1;
119 NibblePath { num_nibbles, bytes }
120 }
121
122 pub(crate) fn push(&mut self, nibble: Nibble) {
124 assert!(ROOT_NIBBLE_HEIGHT > self.num_nibbles);
125 if self.num_nibbles % 2 == 0 {
126 self.bytes.push(u8::from(nibble) << 4);
127 } else {
128 self.bytes[self.num_nibbles / 2] |= u8::from(nibble);
129 }
130 self.num_nibbles += 1;
131 }
132
133 pub(crate) fn pop(&mut self) -> Option<Nibble> {
135 let poped_nibble = if self.num_nibbles % 2 == 0 {
136 self.bytes.last_mut().map(|last_byte| {
137 let nibble = *last_byte & 0x0f;
138 *last_byte &= 0xf0;
139 Nibble::from(nibble)
140 })
141 } else {
142 self.bytes.pop().map(|byte| Nibble::from(byte >> 4))
143 };
144 if poped_nibble.is_some() {
145 self.num_nibbles -= 1;
146 }
147 poped_nibble
148 }
149
150 pub fn last(&self) -> Option<Nibble> {
152 let last_byte_option = self.bytes.last();
153 if self.num_nibbles % 2 == 0 {
154 last_byte_option.map(|last_byte| Nibble::from(*last_byte & 0x0f))
155 } else {
156 let last_byte = last_byte_option.expect("Last byte must exist if num_nibbles is odd.");
157 Some(Nibble::from(*last_byte >> 4))
158 }
159 }
160
161 pub(crate) fn get_bit(&self, i: usize) -> bool {
163 assert!(i < self.num_nibbles * 4);
164 let pos = i / 8;
165 let bit = 7 - i % 8;
166 ((self.bytes[pos] >> bit) & 1) != 0
167 }
168
169 pub fn get_nibble(&self, i: usize) -> Nibble {
171 assert!(i < self.num_nibbles);
172 Nibble::from((self.bytes[i / 2] >> (if i % 2 == 1 { 0 } else { 4 })) & 0xf)
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 {
192 self.num_nibbles
193 }
194
195 pub fn is_empty(&self) -> bool {
197 self.num_nibbles() == 0
198 }
199
200 pub(crate) fn bytes(&self) -> &[u8] {
202 &self.bytes
203 }
204}
205
206pub trait Peekable: Iterator {
207 fn peek(&self) -> Option<Self::Item>;
209}
210
211pub struct BitIterator<'a> {
213 nibble_path: &'a NibblePath,
214 pos: core::ops::Range<usize>,
215}
216
217impl<'a> Peekable for BitIterator<'a> {
218 fn peek(&self) -> Option<Self::Item> {
220 if self.pos.start < self.pos.end {
221 Some(self.nibble_path.get_bit(self.pos.start))
222 } else {
223 None
224 }
225 }
226}
227
228impl<'a> Iterator for BitIterator<'a> {
230 type Item = bool;
231 fn next(&mut self) -> Option<Self::Item> {
232 self.pos.next().map(|i| self.nibble_path.get_bit(i))
233 }
234}
235
236impl<'a> DoubleEndedIterator for BitIterator<'a> {
238 fn next_back(&mut self) -> Option<Self::Item> {
239 self.pos.next_back().map(|i| self.nibble_path.get_bit(i))
240 }
241}
242
243#[derive(Debug, Clone)]
245pub struct NibbleIterator<'a> {
246 nibble_path: &'a NibblePath,
248
249 pos: core::ops::Range<usize>,
252
253 start: usize,
257 }
261
262impl<'a> Iterator for NibbleIterator<'a> {
264 type Item = Nibble;
265 fn next(&mut self) -> Option<Self::Item> {
266 self.pos.next().map(|i| self.nibble_path.get_nibble(i))
267 }
268}
269
270impl<'a> Peekable for NibbleIterator<'a> {
271 fn peek(&self) -> Option<Self::Item> {
273 if self.pos.start < self.pos.end {
274 Some(self.nibble_path.get_nibble(self.pos.start))
275 } else {
276 None
277 }
278 }
279}
280
281impl<'a> NibbleIterator<'a> {
282 fn new(nibble_path: &'a NibblePath, start: usize, end: usize) -> Self {
283 precondition!(start <= end);
284 precondition!(start <= ROOT_NIBBLE_HEIGHT);
285 precondition!(end <= ROOT_NIBBLE_HEIGHT);
286 Self {
287 nibble_path,
288 pos: (start..end),
289 start,
290 }
291 }
292
293 pub fn visited_nibbles(&self) -> NibbleIterator<'a> {
295 assume!(self.start <= self.pos.start); assume!(self.pos.start <= ROOT_NIBBLE_HEIGHT); Self::new(self.nibble_path, self.start, self.pos.start)
298 }
299
300 pub fn remaining_nibbles(&self) -> NibbleIterator<'a> {
302 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)
305 }
306
307 pub fn bits(&self) -> BitIterator<'a> {
309 assume!(self.pos.start <= self.pos.end); assume!(self.pos.end <= ROOT_NIBBLE_HEIGHT); BitIterator {
312 nibble_path: self.nibble_path,
313 pos: (self.pos.start * 4..self.pos.end * 4),
314 }
315 }
316
317 pub fn get_nibble_path(&self) -> NibblePath {
320 self.visited_nibbles()
321 .chain(self.remaining_nibbles())
322 .collect()
323 }
324
325 pub fn num_nibbles(&self) -> usize {
327 assume!(self.start <= self.pos.end); self.pos.end - self.start
329 }
330
331 pub fn is_finished(&self) -> bool {
333 self.peek().is_none()
334 }
335}
336
337pub fn skip_common_prefix<I1, I2>(x: &mut I1, y: &mut I2) -> usize
340where
341 I1: Iterator + Peekable,
342 I2: Iterator + Peekable,
343 <I1 as Iterator>::Item: core::cmp::PartialEq<<I2 as Iterator>::Item>,
344{
345 let mut count = 0;
346 loop {
347 let x_peek = x.peek();
348 let y_peek = y.peek();
349 if x_peek.is_none()
350 || y_peek.is_none()
351 || x_peek.expect("cannot be none") != y_peek.expect("cannot be none")
352 {
353 break;
354 }
355 count += 1;
356 x.next();
357 y.next();
358 }
359 count
360}