trie_db/nibble/
nibbleslice.rs

1// Copyright 2017, 2018 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//! Nibble-orientated view onto byte-slice, allowing nibble-precision offsets.
16
17use super::{nibble_ops, BackingByteVec, NibbleSlice, NibbleSliceIterator, NibbleVec};
18#[cfg(feature = "std")]
19use crate::rstd::fmt;
20use crate::{node::NodeKey, node_codec::Partial, rstd::cmp::*};
21use hash_db::Prefix;
22
23impl<'a> Iterator for NibbleSliceIterator<'a> {
24	type Item = u8;
25	fn next(&mut self) -> Option<u8> {
26		self.i += 1;
27		match self.i <= self.p.len() {
28			true => Some(self.p.at(self.i - 1)),
29			false => None,
30		}
31	}
32}
33
34impl<'a> NibbleSlice<'a> {
35	/// Create a new nibble slice with the given byte-slice.
36	pub fn new(data: &'a [u8]) -> Self {
37		NibbleSlice::new_slice(data, 0)
38	}
39
40	/// Create a new nibble slice with the given byte-slice with a nibble offset.
41	pub fn new_offset(data: &'a [u8], offset: usize) -> Self {
42		Self::new_slice(data, offset)
43	}
44
45	fn new_slice(data: &'a [u8], offset: usize) -> Self {
46		NibbleSlice { data, offset }
47	}
48
49	/// Get an iterator for the series of nibbles.
50	pub fn iter(&'a self) -> NibbleSliceIterator<'a> {
51		NibbleSliceIterator { p: self, i: 0 }
52	}
53
54	/// Get nibble slice from a `NodeKey`.
55	pub fn from_stored(i: &NodeKey) -> NibbleSlice {
56		NibbleSlice::new_offset(&i.1[..], i.0)
57	}
58
59	/// Helper function to create a owned `NodeKey` from this `NibbleSlice`.
60	pub fn to_stored(&self) -> NodeKey {
61		let split = self.offset / nibble_ops::NIBBLE_PER_BYTE;
62		let offset = self.offset % nibble_ops::NIBBLE_PER_BYTE;
63		(offset, self.data[split..].into())
64	}
65
66	/// Helper function to create a owned `NodeKey` from this `NibbleSlice`,
67	/// and for a given number of nibble.
68	/// Warning this method can be slow (number of nibble does not align the
69	/// original padding).
70	pub fn to_stored_range(&self, nb: usize) -> NodeKey {
71		if nb >= self.len() {
72			return self.to_stored()
73		}
74		if (self.offset + nb) % nibble_ops::NIBBLE_PER_BYTE == 0 {
75			// aligned
76			let start = self.offset / nibble_ops::NIBBLE_PER_BYTE;
77			let end = (self.offset + nb) / nibble_ops::NIBBLE_PER_BYTE;
78			(
79				self.offset % nibble_ops::NIBBLE_PER_BYTE,
80				BackingByteVec::from_slice(&self.data[start..end]),
81			)
82		} else {
83			// unaligned
84			let start = self.offset / nibble_ops::NIBBLE_PER_BYTE;
85			let end = (self.offset + nb) / nibble_ops::NIBBLE_PER_BYTE;
86			let ea = BackingByteVec::from_slice(&self.data[start..=end]);
87			let ea_offset = self.offset % nibble_ops::NIBBLE_PER_BYTE;
88			let n_offset = nibble_ops::number_padding(nb);
89			let mut result = (ea_offset, ea);
90			nibble_ops::shift_key(&mut result, n_offset);
91			result.1.pop();
92			result
93		}
94	}
95
96	/// Return true if the slice contains no nibbles.
97	pub fn is_empty(&self) -> bool {
98		self.len() == 0
99	}
100
101	/// Get the length (in nibbles, naturally) of this slice.
102	#[inline]
103	pub fn len(&self) -> usize {
104		self.data.len() * nibble_ops::NIBBLE_PER_BYTE - self.offset
105	}
106
107	/// Get the nibble at position `i`.
108	#[inline(always)]
109	pub fn at(&self, i: usize) -> u8 {
110		nibble_ops::at(&self, i)
111	}
112
113	/// Return object which represents a view on to this slice (further) offset by `i` nibbles.
114	pub fn mid(&self, i: usize) -> NibbleSlice<'a> {
115		NibbleSlice { data: self.data, offset: self.offset + i }
116	}
117
118	/// Advance the view on the slice by `i` nibbles.
119	pub fn advance(&mut self, i: usize) {
120		debug_assert!(self.len() >= i);
121		self.offset += i;
122	}
123
124	/// Move back to a previously valid fix offset position.
125	pub fn back(&self, i: usize) -> NibbleSlice<'a> {
126		NibbleSlice { data: self.data, offset: i }
127	}
128
129	/// Do we start with the same nibbles as the whole of `them`?
130	pub fn starts_with(&self, them: &Self) -> bool {
131		self.common_prefix(them) == them.len()
132	}
133
134	/// How many of the same nibbles at the beginning do we match with `them`?
135	pub fn common_prefix(&self, them: &Self) -> usize {
136		let self_align = self.offset % nibble_ops::NIBBLE_PER_BYTE;
137		let them_align = them.offset % nibble_ops::NIBBLE_PER_BYTE;
138		if self_align == them_align {
139			let mut self_start = self.offset / nibble_ops::NIBBLE_PER_BYTE;
140			let mut them_start = them.offset / nibble_ops::NIBBLE_PER_BYTE;
141			let mut first = 0;
142			if self_align != 0 {
143				if nibble_ops::pad_right(self.data[self_start]) !=
144					nibble_ops::pad_right(them.data[them_start])
145				{
146					// warning only for radix 16
147					return 0
148				}
149				self_start += 1;
150				them_start += 1;
151				first += 1;
152			}
153			nibble_ops::biggest_depth(&self.data[self_start..], &them.data[them_start..]) + first
154		} else {
155			let s = min(self.len(), them.len());
156			let mut i = 0usize;
157			while i < s {
158				if self.at(i) != them.at(i) {
159					break
160				}
161				i += 1;
162			}
163			i
164		}
165	}
166
167	/// Return `Partial` representation of this slice:
168	/// first encoded byte and following slice.
169	pub fn right(&'a self) -> Partial {
170		let split = self.offset / nibble_ops::NIBBLE_PER_BYTE;
171		let nb = (self.len() % nibble_ops::NIBBLE_PER_BYTE) as u8;
172		if nb > 0 {
173			((nb, nibble_ops::pad_right(self.data[split])), &self.data[split + 1..])
174		} else {
175			((0, 0), &self.data[split..])
176		}
177	}
178
179	/// Return an iterator over `Partial` bytes representation.
180	pub fn right_iter(&'a self) -> impl Iterator<Item = u8> + 'a {
181		let (mut first, sl) = self.right();
182		let mut ix = 0;
183		crate::rstd::iter::from_fn(move || {
184			if first.0 > 0 {
185				first.0 = 0;
186				Some(nibble_ops::pad_right(first.1))
187			} else if ix < sl.len() {
188				ix += 1;
189				Some(sl[ix - 1])
190			} else {
191				None
192			}
193		})
194	}
195
196	/// Return `Partial` bytes iterator over a range of byte..
197	/// Warning can be slow when unaligned (similar to `to_stored_range`).
198	pub fn right_range_iter(&'a self, to: usize) -> impl Iterator<Item = u8> + 'a {
199		let mut nib_res = to % nibble_ops::NIBBLE_PER_BYTE;
200		let aligned_i = (self.offset + to) % nibble_ops::NIBBLE_PER_BYTE;
201		let aligned = aligned_i == 0;
202		let mut ix = self.offset / nibble_ops::NIBBLE_PER_BYTE;
203		let ix_lim = (self.offset + to) / nibble_ops::NIBBLE_PER_BYTE;
204		crate::rstd::iter::from_fn(move || {
205			if aligned {
206				if nib_res > 0 {
207					let v = nibble_ops::pad_right(self.data[ix]);
208					nib_res = 0;
209					ix += 1;
210					Some(v)
211				} else if ix < ix_lim {
212					ix += 1;
213					Some(self.data[ix - 1])
214				} else {
215					None
216				}
217			} else {
218				let (s1, s2) = nibble_ops::SPLIT_SHIFTS;
219				// unaligned
220				if nib_res > 0 {
221					let v = self.data[ix] >> s1;
222					let v = nibble_ops::pad_right(v);
223					nib_res = 0;
224					Some(v)
225				} else if ix < ix_lim {
226					ix += 1;
227					let b1 = self.data[ix - 1] << s2;
228					let b2 = self.data[ix] >> s1;
229					Some(b1 | b2)
230				} else {
231					None
232				}
233			}
234		})
235	}
236
237	/// Return left portion of `NibbleSlice`, if the slice
238	/// originates from a full key it will be the `Prefix of
239	/// the node`.
240	pub fn left(&'a self) -> Prefix {
241		let split = self.offset / nibble_ops::NIBBLE_PER_BYTE;
242		let ix = (self.offset % nibble_ops::NIBBLE_PER_BYTE) as u8;
243		if ix == 0 {
244			(&self.data[..split], None)
245		} else {
246			(&self.data[..split], Some(nibble_ops::pad_left(self.data[split])))
247		}
248	}
249
250	/// Get [`Prefix`] representation of the inner data.
251	///
252	/// This means the entire inner data will be returned as [`Prefix`], ignoring any `offset`.
253	pub fn original_data_as_prefix(&self) -> Prefix {
254		(&self.data, None)
255	}
256
257	/// Owned version of a `Prefix` from a `left` method call.
258	pub fn left_owned(&'a self) -> (BackingByteVec, Option<u8>) {
259		let (a, b) = self.left();
260		(a.into(), b)
261	}
262
263	/// Same as [`Self::starts_with`] but using [`NibbleVec`].
264	pub fn starts_with_vec(&self, other: &NibbleVec) -> bool {
265		if self.len() < other.len() {
266			return false
267		}
268
269		match other.as_nibbleslice() {
270			Some(other) => self.starts_with(&other),
271			None => {
272				for i in 0..other.len() {
273					if self.at(i) != other.at(i) {
274						return false
275					}
276				}
277				true
278			},
279		}
280	}
281}
282
283impl<'a> From<NibbleSlice<'a>> for NodeKey {
284	fn from(slice: NibbleSlice<'a>) -> NodeKey {
285		(slice.offset, slice.data.into())
286	}
287}
288
289impl<'a> PartialEq for NibbleSlice<'a> {
290	fn eq(&self, them: &Self) -> bool {
291		self.len() == them.len() && self.starts_with(them)
292	}
293}
294
295impl<'a> PartialEq<NibbleVec> for NibbleSlice<'a> {
296	fn eq(&self, other: &NibbleVec) -> bool {
297		if self.len() != other.len() {
298			return false
299		}
300
301		match other.as_nibbleslice() {
302			Some(other) => *self == other,
303			None => self.iter().enumerate().all(|(index, l)| l == other.at(index)),
304		}
305	}
306}
307
308impl<'a> Eq for NibbleSlice<'a> {}
309
310impl<'a> PartialOrd for NibbleSlice<'a> {
311	fn partial_cmp(&self, them: &Self) -> Option<Ordering> {
312		Some(self.cmp(them))
313	}
314}
315
316impl<'a> Ord for NibbleSlice<'a> {
317	fn cmp(&self, them: &Self) -> Ordering {
318		let s = min(self.len(), them.len());
319		let mut i = 0usize;
320		while i < s {
321			match self.at(i).partial_cmp(&them.at(i)).unwrap() {
322				Ordering::Less => return Ordering::Less,
323				Ordering::Greater => return Ordering::Greater,
324				_ => i += 1,
325			}
326		}
327		self.len().cmp(&them.len())
328	}
329}
330
331#[cfg(feature = "std")]
332impl<'a> fmt::Debug for NibbleSlice<'a> {
333	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
334		for i in 0..self.len() {
335			match i {
336				0 => write!(f, "{:01x}", self.at(i))?,
337				_ => write!(f, "'{:01x}", self.at(i))?,
338			}
339		}
340		Ok(())
341	}
342}
343
344#[cfg(test)]
345mod tests {
346	use crate::nibble::{BackingByteVec, NibbleSlice};
347	static D: &'static [u8; 3] = &[0x01u8, 0x23, 0x45];
348
349	#[test]
350	fn basics() {
351		let n = NibbleSlice::new(D);
352		assert_eq!(n.len(), 6);
353		assert!(!n.is_empty());
354
355		let n = NibbleSlice::new_offset(D, 6);
356		assert!(n.is_empty());
357
358		let n = NibbleSlice::new_offset(D, 3);
359		assert_eq!(n.len(), 3);
360		for i in 0..3 {
361			assert_eq!(n.at(i), i as u8 + 3);
362		}
363	}
364
365	#[test]
366	fn iterator() {
367		let n = NibbleSlice::new(D);
368		let mut nibbles: Vec<u8> = vec![];
369		nibbles.extend(n.iter());
370		assert_eq!(nibbles, (0u8..6).collect::<Vec<_>>())
371	}
372
373	#[test]
374	fn mid() {
375		let n = NibbleSlice::new(D);
376		let m = n.mid(2);
377		for i in 0..4 {
378			assert_eq!(m.at(i), i as u8 + 2);
379		}
380		let m = n.mid(3);
381		for i in 0..3 {
382			assert_eq!(m.at(i), i as u8 + 3);
383		}
384	}
385
386	#[test]
387	fn encoded_pre() {
388		let n = NibbleSlice::new(D);
389		assert_eq!(n.to_stored(), (0, BackingByteVec::from_slice(&[0x01, 0x23, 0x45])));
390		assert_eq!(n.mid(1).to_stored(), (1, BackingByteVec::from_slice(&[0x01, 0x23, 0x45])));
391		assert_eq!(n.mid(2).to_stored(), (0, BackingByteVec::from_slice(&[0x23, 0x45])));
392		assert_eq!(n.mid(3).to_stored(), (1, BackingByteVec::from_slice(&[0x23, 0x45])));
393	}
394
395	#[test]
396	fn from_encoded_pre() {
397		let n = NibbleSlice::new(D);
398		let stored: BackingByteVec = [0x01, 0x23, 0x45][..].into();
399		assert_eq!(n, NibbleSlice::from_stored(&(0, stored.clone())));
400		assert_eq!(n.mid(1), NibbleSlice::from_stored(&(1, stored)));
401	}
402
403	#[test]
404	fn range_iter() {
405		let n = NibbleSlice::new(D);
406		for i in [
407			vec![],
408			vec![0x00],
409			vec![0x01],
410			vec![0x00, 0x12],
411			vec![0x01, 0x23],
412			vec![0x00, 0x12, 0x34],
413			vec![0x01, 0x23, 0x45],
414		]
415		.iter()
416		.enumerate()
417		{
418			range_iter_test(n, i.0, None, &i.1[..]);
419		}
420		for i in [
421			vec![],
422			vec![0x01],
423			vec![0x12],
424			vec![0x01, 0x23],
425			vec![0x12, 0x34],
426			vec![0x01, 0x23, 0x45],
427		]
428		.iter()
429		.enumerate()
430		{
431			range_iter_test(n, i.0, Some(1), &i.1[..]);
432		}
433		for i in [vec![], vec![0x02], vec![0x23], vec![0x02, 0x34], vec![0x23, 0x45]]
434			.iter()
435			.enumerate()
436		{
437			range_iter_test(n, i.0, Some(2), &i.1[..]);
438		}
439		for i in [vec![], vec![0x03], vec![0x34], vec![0x03, 0x45]].iter().enumerate() {
440			range_iter_test(n, i.0, Some(3), &i.1[..]);
441		}
442	}
443
444	fn range_iter_test(n: NibbleSlice, nb: usize, mid: Option<usize>, res: &[u8]) {
445		let n = if let Some(i) = mid { n.mid(i) } else { n };
446		assert_eq!(&n.right_range_iter(nb).collect::<Vec<_>>()[..], res);
447	}
448
449	#[test]
450	fn shared() {
451		let n = NibbleSlice::new(D);
452
453		let other = &[0x01u8, 0x23, 0x01, 0x23, 0x45, 0x67];
454		let m = NibbleSlice::new(other);
455
456		assert_eq!(n.common_prefix(&m), 4);
457		assert_eq!(m.common_prefix(&n), 4);
458		assert_eq!(n.mid(1).common_prefix(&m.mid(1)), 3);
459		assert_eq!(n.mid(1).common_prefix(&m.mid(2)), 0);
460		assert_eq!(n.common_prefix(&m.mid(4)), 6);
461		assert!(!n.starts_with(&m.mid(4)));
462		assert!(m.mid(4).starts_with(&n));
463	}
464
465	#[test]
466	fn compare() {
467		let other = &[0x01u8, 0x23, 0x01, 0x23, 0x45];
468		let n = NibbleSlice::new(D);
469		let m = NibbleSlice::new(other);
470
471		assert!(n != m);
472		assert!(n > m);
473		assert!(m < n);
474
475		assert!(n == m.mid(4));
476		assert!(n >= m.mid(4));
477		assert!(n <= m.mid(4));
478	}
479}