trie/merkle/
nibble.rs

1//! Merkle nibble types.
2
3use rlp::{RlpStream, Rlp};
4use std::cmp::min;
5
6/// Represents a nibble. A 16-variant value.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum Nibble {
9    N0, N1, N2, N3, N4, N5, N6, N7,
10    N8, N9, N10, N11, N12, N13, N14, N15,
11}
12
13impl From<usize> for Nibble {
14    fn from(val: usize) -> Nibble {
15        match val {
16            0 => Nibble::N0, 1 => Nibble::N1, 2 => Nibble::N2, 3 =>
17            Nibble::N3, 4 => Nibble::N4, 5 => Nibble::N5, 6 =>
18            Nibble::N6, 7 => Nibble::N7, 8 => Nibble::N8, 9 =>
19            Nibble::N9, 10 => Nibble::N10, 11 => Nibble::N11, 12 =>
20            Nibble::N12, 13 => Nibble::N13, 14 => Nibble::N14, 15 =>
21            Nibble::N15, _ => panic!(),
22        }
23    }
24}
25
26impl Into<usize> for Nibble {
27    fn into(self) -> usize {
28        match self {
29            Nibble::N0 => 0, Nibble::N1 => 1, Nibble::N2 => 2,
30            Nibble::N3 => 3, Nibble::N4 => 4, Nibble::N5 => 5,
31            Nibble::N6 => 6, Nibble::N7 => 7, Nibble::N8 => 8,
32            Nibble::N9 => 9, Nibble::N10 => 10, Nibble::N11 => 11,
33            Nibble::N12 => 12, Nibble::N13 => 13, Nibble::N14 => 14,
34            Nibble::N15 => 15,
35        }
36    }
37}
38
39impl From<u8> for Nibble {
40    fn from(val: u8) -> Nibble {
41        match val {
42            0 => Nibble::N0, 1 => Nibble::N1, 2 => Nibble::N2, 3 =>
43            Nibble::N3, 4 => Nibble::N4, 5 => Nibble::N5, 6 =>
44            Nibble::N6, 7 => Nibble::N7, 8 => Nibble::N8, 9 =>
45            Nibble::N9, 10 => Nibble::N10, 11 => Nibble::N11, 12 =>
46            Nibble::N12, 13 => Nibble::N13, 14 => Nibble::N14, 15 =>
47            Nibble::N15, _ => panic!(),
48        }
49    }
50}
51
52impl Into<u8> for Nibble {
53    fn into(self) -> u8 {
54        match self {
55            Nibble::N0 => 0, Nibble::N1 => 1, Nibble::N2 => 2,
56            Nibble::N3 => 3, Nibble::N4 => 4, Nibble::N5 => 5,
57            Nibble::N6 => 6, Nibble::N7 => 7, Nibble::N8 => 8,
58            Nibble::N9 => 9, Nibble::N10 => 10, Nibble::N11 => 11,
59            Nibble::N12 => 12, Nibble::N13 => 13, Nibble::N14 => 14,
60            Nibble::N15 => 15,
61        }
62    }
63}
64
65/// A nibble type.
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67pub enum NibbleType {
68    Leaf,
69    Extension
70}
71
72/// A nibble vector.
73pub type NibbleVec = Vec<Nibble>;
74/// A nibble slice.
75pub type NibbleSlice<'a> = &'a [Nibble];
76
77/// Given a key, return the corresponding nibble.
78pub fn from_key(key: &[u8]) -> NibbleVec {
79    let mut vec = NibbleVec::new();
80
81    for i in 0..(key.len()*2) {
82        if i & 1 == 0 { // even
83            vec.push(((key[i / 2] & 0xf0) >> 4).into());
84        } else {
85            vec.push((key[i / 2] & 0x0f).into());
86        }
87    }
88
89    vec
90}
91
92/// Given a nibble, return the corresponding key.
93pub fn into_key(nibble: NibbleSlice) -> Vec<u8> {
94    let mut ret = Vec::new();
95
96    for i in 0..nibble.len() {
97        if i & 1 == 0 { // even
98            let value: u8 = nibble[i].into();
99            ret.push(value << 4);
100        } else {
101            let value: u8 = nibble[i].into();
102            ret[i / 2] |= value;
103        }
104    }
105
106    ret
107}
108
109/// Decode a nibble from RLP.
110pub fn decode(rlp: &Rlp) -> (NibbleVec, NibbleType) {
111    let mut vec = NibbleVec::new();
112
113    let data = rlp.data();
114    let start_odd = if data[0] & 0b00010000 == 0b00010000 { true } else { false };
115    let start_index = if start_odd { 1 } else { 2 };
116    let is_leaf = data[0] & 0b00100000 == 0b00100000;
117
118    let len = data.len() * 2;
119
120    for i in start_index..len {
121        if i & 1 == 0 { // even
122            vec.push(((data[i / 2] & 0xf0) >> 4).into());
123        } else {
124            vec.push((data[i / 2] & 0x0f).into());
125        }
126    }
127
128    (vec, if is_leaf { NibbleType::Leaf } else { NibbleType::Extension })
129}
130
131/// Encode a nibble into the given RLP stream.
132pub fn encode(vec: NibbleSlice, typ: NibbleType, s: &mut RlpStream) {
133    let mut ret: Vec<u8> = Vec::new();
134
135    if vec.len() & 1 == 0 { // even
136        ret.push(0b00000000);
137
138        for i in 0..vec.len() {
139            if i & 1 == 0 {
140                let v: u8 = vec[i].into();
141                ret.push(v << 4);
142            } else {
143                let end = ret.len() - 1;
144                let v: u8 = vec[i].into();
145                ret[end] |= v;
146            }
147        }
148    } else {
149        ret.push(0b00010000);
150
151        for i in 0..vec.len() {
152            if i & 1 == 0 {
153                let end = ret.len() - 1;
154                let v: u8 = vec[i].into();
155                ret[end] |= v;
156            } else {
157                let v: u8 = vec[i].into();
158                ret.push(v << 4);
159            }
160        }
161    }
162
163    ret[0] |= match typ {
164        NibbleType::Leaf => 0b00100000,
165        NibbleType::Extension => 0b00000000
166    };
167
168    s.append(&ret);
169}
170
171/// Common prefix for two nibbles.
172pub fn common<'a, 'b>(a: NibbleSlice<'a>, b: NibbleSlice<'b>) -> NibbleSlice<'a> {
173    let mut common_len = 0;
174
175    for i in 0..min(a.len(), b.len()) {
176        if a[i] == b[i] {
177            common_len += 1;
178        } else {
179            break;
180        }
181    }
182
183    &a[0..common_len]
184}
185
186/// Common prefix for two nibbles. Return the sub nibbles.
187pub fn common_with_sub<'a, 'b>(
188    a: NibbleSlice<'a>, b: NibbleSlice<'b>
189) -> (NibbleSlice<'a>, NibbleVec, NibbleVec) {
190    let common = common(a, b);
191    let asub = a[common.len()..].into();
192    let bsub = b[common.len()..].into();
193
194    (common, asub, bsub)
195}
196
197/// Common prefix for all provided nibbles.
198pub fn common_all<'a, T: Iterator<Item=NibbleSlice<'a>>>(mut iter: T) -> NibbleSlice<'a> {
199    let first = match iter.next() {
200        Some(val) => val,
201        None => return &[],
202    };
203    let second = match iter.next() {
204        Some(val) => val,
205        None => return first,
206    };
207
208    let mut common_cur = common(first, second);
209    for key in iter {
210        common_cur = common(common_cur, key);
211    }
212
213    common_cur
214}
215
216#[cfg(test)]
217mod tests {
218    use super::*;
219
220    #[test]
221    fn from_into_key() {
222        let key = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 244, 233, 188];
223
224        assert_eq!(key, into_key(&from_key(&key)));
225    }
226}