tetsy_trie_db/nibble/
nibblevec.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//! An owning, nibble-oriented byte vector.
16
17use crate::nibble::{NibbleSlice, BackingByteVec};
18use crate::nibble::nibble_ops;
19use tetsy_hash_db::Prefix;
20use crate::node_codec::Partial;
21use super::NibbleVec;
22
23impl Default for NibbleVec {
24	fn default() -> Self {
25		NibbleVec::new()
26	}
27}
28
29impl NibbleVec {
30	/// Make a new `NibbleVec`.
31	pub fn new() -> Self {
32		NibbleVec {
33			inner: BackingByteVec::new(),
34			len: 0,
35		}
36	}
37
38	/// Length of the `NibbleVec`.
39	#[inline(always)]
40	pub fn len(&self) -> usize { self.len }
41
42	/// Retrurns true if `NibbleVec` has zero length.
43	pub fn is_empty(&self) -> bool { self.len == 0 }
44
45	/// Try to get the nibble at the given offset.
46	#[inline]
47	pub fn at(&self, idx: usize) -> u8 {
48		let ix = idx / nibble_ops::NIBBLE_PER_BYTE;
49		let pad = idx % nibble_ops::NIBBLE_PER_BYTE;
50		nibble_ops::at_left(pad as u8, self.inner[ix])
51	}
52
53	/// Push a nibble onto the `NibbleVec`. Ignores the high 4 bits.
54	pub fn push(&mut self, nibble: u8) {
55		let i = self.len % nibble_ops::NIBBLE_PER_BYTE;
56
57		if i == 0 {
58			self.inner.push(nibble_ops::push_at_left(0, nibble, 0));
59		} else {
60			let output = self.inner.last_mut()
61				.expect("len != 0 since len % 2 != 0; inner has a last element; qed");
62			*output = nibble_ops::push_at_left(i as u8, nibble, *output);
63		}
64		self.len += 1;
65	}
66
67	/// Try to pop a nibble off the `NibbleVec`. Fails if len == 0.
68	pub fn pop(&mut self) -> Option<u8> {
69		if self.is_empty() {
70			return None;
71		}
72		let byte = self.inner.pop().expect("len != 0; inner has last elem; qed");
73		self.len -= 1;
74		let i_new = self.len % nibble_ops::NIBBLE_PER_BYTE;
75		if i_new != 0 {
76			self.inner.push(nibble_ops::pad_left(byte));
77		}
78		Some(nibble_ops::at_left(i_new as u8, byte))
79	}
80
81	/// Remove then n last nibbles in a faster way than popping n times.
82	pub fn drop_lasts(&mut self, n: usize) {
83		if n == 0 { return; }
84		if n >= self.len {
85			self.clear();
86			return;
87		}
88		let end = self.len - n;
89		let end_index = end / nibble_ops::NIBBLE_PER_BYTE
90			+ if end % nibble_ops::NIBBLE_PER_BYTE == 0 { 0 } else { 1 };
91		(end_index..self.inner.len()).for_each(|_| { self.inner.pop(); });
92		self.len = end;
93		let pos = self.len % nibble_ops::NIBBLE_PER_BYTE;
94		if pos != 0 {
95			let kl = self.inner.len() - 1;
96			self.inner[kl] = nibble_ops::pad_left(self.inner[kl]);
97		}
98	}
99
100	/// Get `Prefix` representation of this `NibbleVec`.
101	pub fn as_prefix(&self) -> Prefix {
102		let split = self.len / nibble_ops::NIBBLE_PER_BYTE;
103		let pos = (self.len % nibble_ops::NIBBLE_PER_BYTE) as u8;
104		if pos == 0 {
105			(&self.inner[..split], None)
106		} else {
107			(&self.inner[..split], Some(nibble_ops::pad_left(self.inner[split])))
108		}
109	}
110
111	/// Append another `NibbleVec`. Can be slow (alignement of second vec).
112	pub fn append(&mut self, v: &NibbleVec) {
113
114		if v.len == 0 { return; }
115		let final_len = self.len + v.len;
116		let offset = self.len % nibble_ops::NIBBLE_PER_BYTE;
117		let final_offset = final_len % nibble_ops::NIBBLE_PER_BYTE;
118		let last_index = self.len / nibble_ops::NIBBLE_PER_BYTE;
119		if offset > 0 {
120			let (s1, s2) = nibble_ops::SPLIT_SHIFTS;
121			self.inner[last_index] = nibble_ops::pad_left(self.inner[last_index])
122				| (v.inner[0] >> s2);
123			(0..v.inner.len() - 1)
124				.for_each(|i| self.inner.push(v.inner[i] << s1 | v.inner[i+1] >> s2));
125			if final_offset > 0 {
126				self.inner.push(v.inner[v.inner.len() - 1] << s1);
127			}
128		} else {
129			(0..v.inner.len()).for_each(|i| self.inner.push(v.inner[i]));
130		}
131		self.len += v.len;
132	}
133
134	/// Append a `Partial`. Can be slow (alignement of partial).
135	pub fn append_partial(&mut self, (start_byte, sl): Partial) {
136		if start_byte.0 == 1 {
137			self.push(nibble_ops::at_left(1, start_byte.1));
138		}
139		let pad = self.inner.len() * nibble_ops::NIBBLE_PER_BYTE - self.len;
140		if pad == 0 {
141			self.inner.extend_from_slice(&sl[..]);
142		} else {
143			let kend = self.inner.len() - 1;
144			if sl.len() > 0 {
145				self.inner[kend] = nibble_ops::pad_left(self.inner[kend]);
146				let (s1, s2) = nibble_ops::SPLIT_SHIFTS;
147				self.inner[kend] |= sl[0] >> s1;
148				(0..sl.len() - 1).for_each(|i| self.inner.push(sl[i] << s2 | sl[i+1] >> s1));
149				self.inner.push(sl[sl.len() - 1] << s2);
150			}
151		}
152		self.len += sl.len() * nibble_ops::NIBBLE_PER_BYTE;
153	}
154
155	/// Utility function for chaining two optional appending
156	/// of `NibbleSlice` and/or a byte.
157	/// Can be slow.
158	pub(crate) fn append_optional_slice_and_nibble(
159		&mut self,
160		o_slice: Option<&NibbleSlice>,
161		o_index: Option<u8>,
162	) -> usize {
163		let mut res = 0;
164		if let Some(slice) = o_slice {
165			self.append_partial(slice.right());
166			res += slice.len();
167		}
168		if let Some(ix) = o_index {
169			self.push(ix);
170			res += 1;
171		}
172		res
173	}
174
175	/// Utility function for `append_optional_slice_and_nibble` after a clone.
176	/// Can be slow.
177	pub(crate) fn clone_append_optional_slice_and_nibble(
178		&self,
179		o_slice: Option<&NibbleSlice>,
180		o_index: Option<u8>,
181	) -> Self {
182		let mut p = self.clone();
183		p.append_optional_slice_and_nibble(o_slice, o_index);
184		p
185	}
186
187	/// Get the underlying byte slice.
188	pub fn inner(&self) -> &[u8] {
189		&self.inner[..]
190	}
191
192	/// clear
193	pub fn clear(&mut self) {
194		self.inner.clear();
195		self.len = 0;
196	}
197
198	/// Try to treat this `NibbleVec` as a `NibbleSlice`. Works only if there is no padding.
199	pub fn as_nibbleslice(&self) -> Option<NibbleSlice> {
200		if self.len % nibble_ops::NIBBLE_PER_BYTE == 0 {
201			Some(NibbleSlice::new(self.inner()))
202		} else {
203			None
204		}
205	}
206
207	/// Do we start with the same nibbles as the whole of `them`?
208	pub fn starts_with(&self, other: &Self) -> bool {
209		if self.len() < other.len() {
210			return false;
211		}
212		let byte_len = other.len() / nibble_ops::NIBBLE_PER_BYTE;
213		if &self.inner[..byte_len] != &other.inner[..byte_len] {
214			return false;
215		}
216		for pad in 0..(other.len() - byte_len * nibble_ops::NIBBLE_PER_BYTE) {
217			let self_nibble = nibble_ops::at_left(pad as u8, self.inner[byte_len]);
218			let other_nibble = nibble_ops::at_left(pad as u8, other.inner[byte_len]);
219			if self_nibble != other_nibble {
220				return false;
221			}
222		}
223		true
224	}
225}
226
227impl<'a> From<NibbleSlice<'a>> for NibbleVec {
228	fn from(s: NibbleSlice<'a>) -> Self {
229		let mut v = NibbleVec::new();
230		for i in 0..s.len() {
231			v.push(s.at(i));
232		}
233		v
234	}
235}
236
237#[cfg(test)]
238mod tests {
239	use crate::nibble::NibbleVec;
240	use crate::nibble::nibble_ops;
241
242	#[test]
243	fn push_pop() {
244		let mut v = NibbleVec::new();
245
246		for i in 0..(nibble_ops::NIBBLE_PER_BYTE * 3) {
247			let iu8 = (i % nibble_ops::NIBBLE_PER_BYTE) as u8;
248			v.push(iu8);
249			assert_eq!(v.len() - 1, i);
250			assert_eq!(v.at(i), iu8);
251		}
252
253		for i in (0..(nibble_ops::NIBBLE_PER_BYTE * 3)).rev() {
254			let iu8 = (i % nibble_ops::NIBBLE_PER_BYTE) as u8;
255			let a = v.pop();
256			assert_eq!(a, Some(iu8));
257			assert_eq!(v.len(), i);
258		}
259	}
260
261	#[test]
262	fn append_partial() {
263		append_partial_inner(&[1, 2, 3], &[], ((1, 1), &[0x23]));
264		append_partial_inner(&[1, 2, 3], &[1], ((0, 0), &[0x23]));
265		append_partial_inner(&[0, 1, 2, 3], &[0], ((1, 1), &[0x23]));
266	}
267
268	fn append_partial_inner(res: &[u8], init: &[u8], partial: ((u8, u8), &[u8])) {
269		let mut resv = NibbleVec::new();
270		res.iter().for_each(|r| resv.push(*r));
271		let mut initv = NibbleVec::new();
272		init.iter().for_each(|r| initv.push(*r));
273		initv.append_partial(partial);
274		assert_eq!(resv, initv);
275	}
276
277	#[test]
278	fn drop_lasts_test() {
279		let test_trun = |a: &[u8], b: usize, c: (&[u8], usize)| {
280			let mut k = NibbleVec::new();
281			for v in a {
282				k.push(*v);
283			}
284			k.drop_lasts(b);
285			assert_eq!((&k.inner[..], k.len), c);
286		};
287		test_trun(&[1, 2, 3, 4], 0, (&[0x12, 0x34], 4));
288		test_trun(&[1, 2, 3, 4], 1, (&[0x12, 0x30], 3));
289		test_trun(&[1, 2, 3, 4], 2, (&[0x12], 2));
290		test_trun(&[1, 2, 3, 4], 3, (&[0x10], 1));
291		test_trun(&[1, 2, 3, 4], 4, (&[], 0));
292		test_trun(&[1, 2, 3, 4], 5, (&[], 0));
293		test_trun(&[1, 2, 3], 0, (&[0x12, 0x30], 3));
294		test_trun(&[1, 2, 3], 1, (&[0x12], 2));
295		test_trun(&[1, 2, 3], 2, (&[0x10], 1));
296		test_trun(&[1, 2, 3], 3, (&[], 0));
297		test_trun(&[1, 2, 3], 4, (&[], 0));
298	}
299
300}