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}