1#[cfg(test)]
2mod test;
34use smallvec::{Array, SmallVec};
56use std::convert::{From, Into};
7use std::fmt::{self, Debug, Formatter};
8use std::iter::FromIterator;
910/// A `NibbleVec` backed by a `SmallVec` with 64 inline element slots.
11/// This will not allocate until more than 64 elements are added.
12pub type Nibblet = NibbleVec<[u8; 64]>;
1314/// A data-structure for storing a sequence of 4-bit values.
15///
16/// Values are stored in a `Vec<u8>`, with two values per byte.
17///
18/// Values at even indices are stored in the most-significant half of their byte,
19/// while values at odd indices are stored in the least-significant half.
20///
21/// Imagine a vector of [MSB][msb-wiki] first bytes, and you'll be right.
22///
23/// n = [_ _ | _ _ | _ _]
24///
25/// [msb-wiki]: http://en.wikipedia.org/wiki/Most_significant_bit
26#[derive(Clone, Default)]
27pub struct NibbleVec<A: Array<Item = u8>> {
28 length: usize,
29 data: SmallVec<A>,
30}
3132impl<A: Array<Item = u8>> NibbleVec<A> {
33/// Create an empty nibble vector.
34pub fn new() -> NibbleVec<A> {
35 NibbleVec {
36 length: 0,
37 data: SmallVec::new(),
38 }
39 }
4041/// Create a nibble vector from a vector of bytes.
42 ///
43 /// Each byte is split into two 4-bit entries (MSB, LSB).
44#[inline]
45pub fn from_byte_vec(vec: Vec<u8>) -> NibbleVec<A> {
46let length = 2 * vec.len();
47 NibbleVec {
48 length,
49 data: SmallVec::from_iter(vec),
50 }
51 }
5253/// Returns a byte slice of the nibble vector's contents.
54#[inline]
55pub fn as_bytes(&self) -> &[u8] {
56&self.data[..]
57 }
5859/// Converts a nibble vector into a byte vector.
60 ///
61 /// This consumes the nibble vector, so we do not need to copy its contents.
62#[inline]
63pub fn into_bytes(self) -> Vec<u8> {
64self.data.to_vec()
65 }
6667/// Get the number of elements stored in the vector.
68#[inline]
69pub fn len(&self) -> usize {
70self.length
71 }
7273/// Returns `true` if the nibble vector has a length of 0.
74#[inline]
75pub fn is_empty(&self) -> bool {
76self.data.is_empty()
77 }
7879/// Fetch a single entry from the vector.
80 ///
81 /// Guaranteed to be a value in the interval [0, 15].
82 ///
83 /// **Panics** if `idx >= self.len()`.
84#[inline]
85pub fn get(&self, idx: usize) -> u8 {
86if idx >= self.length {
87panic!(
88"NibbleVec index out of bounds: len is {}, index is {}",
89self.length, idx
90 );
91 }
92let vec_idx = idx / 2;
93match idx % 2 {
94// If the index is even, take the first (most significant) half of the stored byte.
950 => self.data[vec_idx] >> 4,
96// If the index is odd, take the second (least significant) half.
97_ => self.data[vec_idx] & 0x0F,
98 }
99 }
100101/// Add a single nibble to the vector.
102 ///
103 /// Only the 4 least-significant bits of the value are used.
104#[inline]
105pub fn push(&mut self, val: u8) {
106if self.length % 2 == 0 {
107self.data.push(val << 4);
108 } else {
109let vec_len = self.data.len();
110111// Zero the second half of the last byte just to be safe.
112self.data[vec_len - 1] &= 0xF0;
113114// Write the new value.
115self.data[vec_len - 1] |= val & 0x0F;
116 }
117self.length += 1;
118 }
119120/// Split the vector into two parts.
121 ///
122 /// All elements at or following the given index are returned in a new `NibbleVec`,
123 /// with exactly `idx` elements remaining in this vector.
124 ///
125 /// **Panics** if `idx > self.len()`.
126pub fn split(&mut self, idx: usize) -> NibbleVec<A> {
127// assert! is a few percent slower surprisingly
128if idx > self.length {
129panic!(
130"attempted to split past vector end. len is {}, index is {}",
131self.length, idx
132 );
133 } else if idx == self.length {
134 NibbleVec::new()
135 } else if idx % 2 == 0 {
136self.split_even(idx)
137 } else {
138self.split_odd(idx)
139 }
140 }
141142/// Split function for odd *indices*.
143#[inline]
144fn split_odd(&mut self, idx: usize) -> NibbleVec<A> {
145let mut tail = NibbleVec::new();
146147// Perform an overlap copy, copying the last nibble of the original vector only if
148 // the length of the new tail is *odd*.
149let tail_length = self.length - idx;
150let take_last = tail_length % 2 == 1;
151self.overlap_copy(
152 idx / 2,
153self.data.len(),
154&mut tail.data,
155&mut tail.length,
156 take_last,
157 );
158159// Remove the copied bytes, being careful to skip the idx byte.
160for _ in (idx / 2 + 1)..self.data.len() {
161self.data.pop();
162 }
163164// Zero the second half of the index byte so as to maintain the last-nibble invariant.
165self.data[idx / 2] &= 0xF0;
166167// Update the length of the first NibbleVec.
168self.length = idx;
169170 tail
171 }
172173/// Split function for even *indices*.
174#[inline]
175fn split_even(&mut self, idx: usize) -> NibbleVec<A> {
176// Avoid allocating a temporary vector by copying all the bytes in order, then popping them.
177178 // Possible to prove: l_d - ⌊i / 2⌋ = ⌊(l_v - i + 1) / 2⌋
179 // where l_d = self.data.len()
180 // l_v = self.length
181182let half_idx = idx / 2;
183let mut tail = NibbleVec::new();
184185// Copy the bytes.
186for i in half_idx..self.data.len() {
187 tail.data.push(self.data[i]);
188 }
189190// Pop the same bytes.
191for _ in half_idx..self.data.len() {
192self.data.pop();
193 }
194195// Update lengths.
196tail.length = self.length - idx;
197self.length = idx;
198199 tail
200 }
201202/// Copy data between the second half of self.data[start] and
203 /// self.data[end - 1]. The second half of the last entry is included
204 /// if include_last is true.
205#[inline]
206fn overlap_copy(
207&self,
208 start: usize,
209 end: usize,
210 vec: &mut SmallVec<A>,
211 length: &mut usize,
212 include_last: bool,
213 ) {
214// Copy up to the first half of the last byte.
215for i in start..(end - 1) {
216// The first half is the second half of the old entry.
217let first_half = self.data[i] & 0x0f;
218219// The second half is the first half of the next entry.
220let second_half = self.data[i + 1] >> 4;
221222 vec.push((first_half << 4) | second_half);
223*length += 2;
224 }
225226if include_last {
227let last = self.data[end - 1] & 0x0f;
228 vec.push(last << 4);
229*length += 1;
230 }
231 }
232233/// Append another nibble vector whilst consuming this vector.
234#[inline]
235pub fn join(mut self, other: &NibbleVec<A>) -> NibbleVec<A> {
236// If the length is even, we can append directly.
237if self.length % 2 == 0 {
238self.length += other.length;
239self.data.extend_from_slice(&other.data);
240return self;
241 }
242243// If the other vector is empty, bail out.
244if other.is_empty() {
245return self;
246 }
247248// If the length is odd, we have to perform an overlap copy.
249 // Copy the first half of the first element, to make the vector an even length.
250self.push(other.get(0));
251252// Copy the rest of the vector using an overlap copy.
253let take_last = other.len() % 2 == 0;
254 other.overlap_copy(
2550,
256 other.data.len(),
257&mut self.data,
258&mut self.length,
259 take_last,
260 );
261262self
263}
264}
265266impl<A: Array<Item = u8>> PartialEq<NibbleVec<A>> for NibbleVec<A> {
267#[inline]
268fn eq(&self, other: &NibbleVec<A>) -> bool {
269self.length == other.length && self.data == other.data
270 }
271}
272273impl<A: Array<Item = u8>> Eq for NibbleVec<A> {}
274275/// Compare a `NibbleVec` and a slice of bytes *element-by-element*.
276/// Bytes are **not** interpreted as two `NibbleVec` entries.
277impl<A: Array<Item = u8>> PartialEq<[u8]> for NibbleVec<A> {
278#[inline]
279fn eq(&self, other: &[u8]) -> bool {
280if other.len() != self.len() {
281return false;
282 }
283284for (i, x) in other.iter().enumerate() {
285if self.get(i) != *x {
286return false;
287 }
288 }
289true
290}
291}
292293impl<A: Array<Item = u8>> Debug for NibbleVec<A> {
294fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
295write!(fmt, "NibbleVec [")?;
296297if !self.is_empty() {
298write!(fmt, "{}", self.get(0))?;
299 }
300301for i in 1..self.len() {
302write!(fmt, ", {}", self.get(i))?;
303 }
304write!(fmt, "]")
305 }
306}
307308impl<A: Array<Item = u8>> From<Vec<u8>> for NibbleVec<A> {
309#[inline]
310fn from(v: Vec<u8>) -> NibbleVec<A> {
311 NibbleVec::from_byte_vec(v)
312 }
313}
314315impl<'a, A: Array<Item = u8>> From<&'a [u8]> for NibbleVec<A> {
316#[inline]
317fn from(v: &[u8]) -> NibbleVec<A> {
318 NibbleVec::from_byte_vec(v.into())
319 }
320}
321322impl<A: Array<Item = u8>> Into<Vec<u8>> for NibbleVec<A> {
323#[inline]
324fn into(self) -> Vec<u8> {
325self.data.to_vec()
326 }
327}
328329impl<'a, A: Array<Item = u8>> Into<Vec<u8>> for &'a NibbleVec<A> {
330#[inline]
331fn into(self) -> Vec<u8> {
332self.data.to_vec()
333 }
334}