nibble/
vec.rs

1//! Types for arrays of nibbles.
2use std::{slice as stdslice, mem};
3use base::{u4lo, u4};
4use pair::u4x2;
5use slice::{self, NibSliceAligned, NibSliceAlignedMut, NibSliceFull, NibSliceNoR};
6use common::{get_nib, set_nib, shift_left, shift_right};
7
8/// A `Vec` of nibbles.
9#[derive(Clone)]
10pub struct NibVec  {
11    inner: Vec<u4x2>,
12    has_right_lo: bool,
13}
14impl NibVec {
15    /// Creates an empty `ArrayVec`.
16    pub fn new() -> Self {
17        NibVec { inner: Vec::new(), has_right_lo: true }
18    }
19
20    /// Creates a vector from a vector of pairs.
21    pub fn from_pair_vec(inner: Vec<u4x2>) -> Self {
22        NibVec { inner, has_right_lo: true }
23    }
24
25    /// Creates a vector from a vector of bytes.
26    pub fn from_byte_vec(inner: Vec<u8>) -> Self {
27        Self::from_pair_vec(unsafe { mem::transmute(inner) })
28    }
29
30    /// Number of nibbles in the vector.
31    pub fn len(&self) -> usize {
32        (self.inner.len() >> 1).saturating_sub(!self.has_right_lo as usize)
33    }
34
35    /// Whether the vector is empty.
36    pub fn is_empty(&self) -> bool {
37        self.inner.is_empty()
38    }
39
40    /// How many nibbles can be stored in the vector.
41    pub fn capacity(&self) -> usize {
42        self.inner.capacity() >> 1
43    }
44
45    /// Pushes a nibble onto the vector.
46    ///
47    /// # Panics
48    ///
49    /// Panics if the vector is full.
50    pub fn push<T: u4>(&mut self, nib: T) {
51        self.has_right_lo = !self.has_right_lo;
52        if self.has_right_lo {
53            self.inner.push(u4x2::from_hi(nib.to_u4hi()));
54        } else {
55            let i = self.inner.len() - 1;
56            self.inner[i].set_lo(nib);
57        }
58    }
59
60    /// Inserts a nibble into the vector at the given index.
61    pub fn insert<T: u4>(&mut self, index: usize, nib: T) {
62        if self.has_right_lo {
63            self.push(u4lo::from_lo(0));
64        }
65        shift_right(self.inner.as_mut_slice(), index);
66        set_nib(self.inner.as_mut_slice(), index, nib);
67    }
68
69    fn discard_at(&mut self, index: usize) {
70        shift_left(self.inner.as_mut_slice(), index);
71        self.has_right_lo = !self.has_right_lo;
72        if self.has_right_lo {
73            self.inner.pop();
74        }
75    }
76
77    /// Removes a nibble from the vector at the given index, converting it to a high-order nibble.
78    pub fn remove<T: u4>(&mut self, index: usize) -> T {
79        let ret = get_nib(self.inner.as_slice(), index);
80        self.discard_at(index);
81        ret
82    }
83
84    /// Removes a nibble from the vector, converting it to a high-order nibble.
85    pub fn pop<T: u4>(&mut self) -> Option<T> {
86        self.has_right_lo = !self.has_right_lo;
87        if self.has_right_lo {
88            Some(T::from_lo(self.inner[self.inner.len() - 1].lo().to_lo()))
89        } else {
90            self.inner.pop().map(|pair| T::from_hi(pair.hi().to_hi()))
91        }
92    }
93
94    /// Clears the vector, removing all nibbles.
95    pub fn clear(&mut self) {
96        self.inner.clear();
97        self.has_right_lo = true;
98    }
99
100    /// Intreprets this array as a slice.
101    pub fn as_slice(&self) -> NibSliceAligned {
102        if self.has_right_lo {
103            NibSliceAligned::Even(unsafe { &*(&self.inner[..] as *const [u4x2] as *const NibSliceFull) })
104        } else {
105            NibSliceAligned::Odd(unsafe { &*(&self.inner[..] as *const [u4x2] as *const NibSliceNoR) })
106        }
107    }
108
109    /// Intreprets this array as a mutable slice.
110    pub fn as_mut_slice(&mut self) -> NibSliceAlignedMut {
111        if self.has_right_lo {
112            NibSliceAlignedMut::Even(unsafe { &mut *(&mut self.inner[..] as *mut [u4x2] as *mut NibSliceFull) })
113        } else {
114            NibSliceAlignedMut::Odd(unsafe { &mut *(&mut self.inner[..] as *mut [u4x2] as *mut NibSliceNoR) })
115        }
116    }
117}
118impl Default for NibVec {
119    fn default() -> Self {
120        NibVec::new()
121    }
122}
123impl slice::private::Sealed for NibVec {
124    #[inline(always)]
125    fn has_left_hi(&self) -> bool { true }
126    #[inline(always)]
127    fn has_right_lo(&self) -> bool { self.as_slice().has_right_lo() }
128    #[inline(always)]
129    fn iter(&self) -> stdslice::Iter<u4x2> { self.inner.iter() }
130}
131impl slice::private::SealedMut for NibVec {
132    #[inline(always)]
133    fn iter_mut(&mut self) -> stdslice::IterMut<u4x2> { self.inner.iter_mut() }
134}
135impl slice::NibSliceExt for NibVec {}
136impl slice::NibSliceMutExt for NibVec {}