1use std::fmt;
12
13const MAXBYTES: usize = 9;
14
15#[derive(Debug, Clone, PartialEq)]
18pub struct Uvar(Vec<u8>);
19
20impl Uvar {
21    pub fn new(bytes: Vec<u8>) -> Uvar {
24        Uvar(bytes)
25    }
26
27    pub fn to_bytes(self) -> Vec<u8> {
35        self.0
36    }
37
38    pub fn from_bytes(buffer: &[u8]) -> Result<Uvar, UvarError> {
40        if buffer.len() > MAXBYTES {
41            return Err(UvarError::Overflow);
42        }
43
44        let (n, _) = Uvar::take(buffer)?;
45
46        Ok(n)
47    }
48
49    pub fn take(buffer: &[u8]) -> Result<(Uvar, &[u8]), UvarError> {
60        for (i, b) in buffer.into_iter().enumerate() {
61            if b & 0x80 == 0 {
62                let code = Uvar((&buffer[..i + 1]).into());
63                let rest = &buffer[i + 1..];
64
65                return Ok((code, rest));
66            }
67
68            if i >= MAXBYTES {
69                return Err(UvarError::Overflow);
70            }
71        }
72
73        Err(UvarError::Underflow)
74    }
75}
76
77impl fmt::LowerHex for Uvar {
78    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
79        fmt::LowerHex::fmt(&u64::from(self.clone()), f)
80    }
81}
82
83impl fmt::UpperHex for Uvar {
84    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85        fmt::UpperHex::fmt(&u64::from(self.clone()), f)
86    }
87}
88
89impl fmt::Binary for Uvar {
90    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
91        fmt::Binary::fmt(&u64::from(self.clone()), f)
92    }
93}
94
95impl fmt::Display for Uvar {
96    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97        write!(f, "{:02x}", &self)
98    }
99}
100
101impl From<Uvar> for u64 {
102    fn from(uvar: Uvar) -> u64 {
103        let mut n = 0;
104
105        for (i, b) in uvar.to_bytes().iter().enumerate() {
106            n = n << (i * 8) | u64::from(b & 0xFF);
107        }
108
109        n
110    }
111}
112
113impl From<u64> for Uvar {
117    fn from(n: u64) -> Uvar {
118        let mut buffer = Vec::with_capacity(MAXBYTES);
119        let mut value = n.to_be();
120
121        while value > 0 {
122            let k = value & 0xFF;
123            if k != 0 {
124                buffer.push(k as u8);
125            }
126
127            value = value >> 8;
128        }
129
130        Uvar(buffer)
131    }
132}
133
134#[derive(Debug)]
165pub enum UvarError {
166    Overflow,
167    Underflow,
168}
169
170#[cfg(test)]
171mod tests {
172    use super::*;
173
174    #[test]
175    fn from_bytes_single() {
176        let actual = Uvar::from_bytes(&[0x12]).unwrap();
177        let expected = Uvar(vec![0x12]);
178        assert_eq!(actual, expected);
179    }
180
181    #[test]
182    fn from_bytes_multi() {
183        let actual = Uvar::from_bytes(&[0xb2, 0x40]).unwrap();
184        let expected = Uvar(vec![0xb2, 0x40]);
185        assert_eq!(actual, expected);
186    }
187
188    #[test]
189    fn to_bytes() {
190        let actual = Uvar(vec![0xb2, 0x40]).to_bytes();
191        let expected = &[0xb2, 0x40];
192        assert_eq!(&actual, expected);
193    }
194
195    #[test]
196    fn identity() {
197        let actual = Uvar::from_bytes(&[0xb2, 0x40]).unwrap().to_bytes();
198        let expected = &[0xb2, 0x40];
199        assert_eq!(&actual, expected);
200    }
201
202    #[test]
203    fn to_u64() {
204        for (buffer, expected) in &[(vec![0x12], 0x12), (vec![0xb2, 0x40], 0xb240)] {
205            let actual: u64 = Uvar::from_bytes(&buffer).unwrap().into();
206
207            assert_eq!(actual, *expected);
208        }
209    }
210
211    #[test]
212    fn from_u64() {
213        for (buffer, n) in &[(vec![0x12], 0x12), (vec![0xb2, 0x40], 0xb240)] {
214            let num: u64 = *n;
215            let expected = Uvar::from_bytes(&buffer).unwrap();
216            let actual: Uvar = num.into();
217
218            assert_eq!(actual, expected);
219        }
220    }
221
222}