1#[cfg(test)]
2mod test;
3
4use smallvec::{Array, SmallVec};
5
6use std::convert::{From, Into};
7use std::fmt::{self, Debug, Formatter};
8use std::iter::FromIterator;
9
10pub type Nibblet = NibbleVec<[u8; 64]>;
13
14#[derive(Clone, Default)]
27pub struct NibbleVec<A: Array<Item = u8>> {
28 length: usize,
29 data: SmallVec<A>,
30}
31
32impl<A: Array<Item = u8>> NibbleVec<A> {
33 pub fn new() -> NibbleVec<A> {
35 NibbleVec {
36 length: 0,
37 data: SmallVec::new(),
38 }
39 }
40
41 #[inline]
45 pub fn from_byte_vec(vec: Vec<u8>) -> NibbleVec<A> {
46 let length = 2 * vec.len();
47 NibbleVec {
48 length,
49 data: SmallVec::from_iter(vec),
50 }
51 }
52
53 #[inline]
55 pub fn as_bytes(&self) -> &[u8] {
56 &self.data[..]
57 }
58
59 #[inline]
63 pub fn into_bytes(self) -> Vec<u8> {
64 self.data.to_vec()
65 }
66
67 #[inline]
69 pub fn len(&self) -> usize {
70 self.length
71 }
72
73 #[inline]
75 pub fn is_empty(&self) -> bool {
76 self.data.is_empty()
77 }
78
79 #[inline]
85 pub fn get(&self, idx: usize) -> u8 {
86 if idx >= self.length {
87 panic!(
88 "NibbleVec index out of bounds: len is {}, index is {}",
89 self.length, idx
90 );
91 }
92 let vec_idx = idx / 2;
93 match idx % 2 {
94 0 => self.data[vec_idx] >> 4,
96 _ => self.data[vec_idx] & 0x0F,
98 }
99 }
100
101 #[inline]
105 pub fn push(&mut self, val: u8) {
106 if self.length % 2 == 0 {
107 self.data.push(val << 4);
108 } else {
109 let vec_len = self.data.len();
110
111 self.data[vec_len - 1] &= 0xF0;
113
114 self.data[vec_len - 1] |= val & 0x0F;
116 }
117 self.length += 1;
118 }
119
120 pub fn split(&mut self, idx: usize) -> NibbleVec<A> {
127 if idx > self.length {
129 panic!(
130 "attempted to split past vector end. len is {}, index is {}",
131 self.length, idx
132 );
133 } else if idx == self.length {
134 NibbleVec::new()
135 } else if idx % 2 == 0 {
136 self.split_even(idx)
137 } else {
138 self.split_odd(idx)
139 }
140 }
141
142 #[inline]
144 fn split_odd(&mut self, idx: usize) -> NibbleVec<A> {
145 let mut tail = NibbleVec::new();
146
147 let tail_length = self.length - idx;
150 let take_last = tail_length % 2 == 1;
151 self.overlap_copy(
152 idx / 2,
153 self.data.len(),
154 &mut tail.data,
155 &mut tail.length,
156 take_last,
157 );
158
159 for _ in (idx / 2 + 1)..self.data.len() {
161 self.data.pop();
162 }
163
164 self.data[idx / 2] &= 0xF0;
166
167 self.length = idx;
169
170 tail
171 }
172
173 #[inline]
175 fn split_even(&mut self, idx: usize) -> NibbleVec<A> {
176 let half_idx = idx / 2;
183 let mut tail = NibbleVec::new();
184
185 for i in half_idx..self.data.len() {
187 tail.data.push(self.data[i]);
188 }
189
190 for _ in half_idx..self.data.len() {
192 self.data.pop();
193 }
194
195 tail.length = self.length - idx;
197 self.length = idx;
198
199 tail
200 }
201
202 #[inline]
206 fn 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 for i in start..(end - 1) {
216 let first_half = self.data[i] & 0x0f;
218
219 let second_half = self.data[i + 1] >> 4;
221
222 vec.push((first_half << 4) | second_half);
223 *length += 2;
224 }
225
226 if include_last {
227 let last = self.data[end - 1] & 0x0f;
228 vec.push(last << 4);
229 *length += 1;
230 }
231 }
232
233 #[inline]
235 pub fn join(mut self, other: &NibbleVec<A>) -> NibbleVec<A> {
236 if self.length % 2 == 0 {
238 self.length += other.length;
239 self.data.extend_from_slice(&other.data);
240 return self;
241 }
242
243 if other.is_empty() {
245 return self;
246 }
247
248 self.push(other.get(0));
251
252 let take_last = other.len() % 2 == 0;
254 other.overlap_copy(
255 0,
256 other.data.len(),
257 &mut self.data,
258 &mut self.length,
259 take_last,
260 );
261
262 self
263 }
264}
265
266impl<A: Array<Item = u8>> PartialEq<NibbleVec<A>> for NibbleVec<A> {
267 #[inline]
268 fn eq(&self, other: &NibbleVec<A>) -> bool {
269 self.length == other.length && self.data == other.data
270 }
271}
272
273impl<A: Array<Item = u8>> Eq for NibbleVec<A> {}
274
275impl<A: Array<Item = u8>> PartialEq<[u8]> for NibbleVec<A> {
278 #[inline]
279 fn eq(&self, other: &[u8]) -> bool {
280 if other.len() != self.len() {
281 return false;
282 }
283
284 for (i, x) in other.iter().enumerate() {
285 if self.get(i) != *x {
286 return false;
287 }
288 }
289 true
290 }
291}
292
293impl<A: Array<Item = u8>> Debug for NibbleVec<A> {
294 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
295 write!(fmt, "NibbleVec [")?;
296
297 if !self.is_empty() {
298 write!(fmt, "{}", self.get(0))?;
299 }
300
301 for i in 1..self.len() {
302 write!(fmt, ", {}", self.get(i))?;
303 }
304 write!(fmt, "]")
305 }
306}
307
308impl<A: Array<Item = u8>> From<Vec<u8>> for NibbleVec<A> {
309 #[inline]
310 fn from(v: Vec<u8>) -> NibbleVec<A> {
311 NibbleVec::from_byte_vec(v)
312 }
313}
314
315impl<'a, A: Array<Item = u8>> From<&'a [u8]> for NibbleVec<A> {
316 #[inline]
317 fn from(v: &[u8]) -> NibbleVec<A> {
318 NibbleVec::from_byte_vec(v.into())
319 }
320}
321
322impl<A: Array<Item = u8>> Into<Vec<u8>> for NibbleVec<A> {
323 #[inline]
324 fn into(self) -> Vec<u8> {
325 self.data.to_vec()
326 }
327}
328
329impl<'a, A: Array<Item = u8>> Into<Vec<u8>> for &'a NibbleVec<A> {
330 #[inline]
331 fn into(self) -> Vec<u8> {
332 self.data.to_vec()
333 }
334}