cryptonote_varint/
lib.rs

1#![allow(non_snake_case)]
2
3use std::io::{Read, Write};
4use std::ops::{BitAnd, BitOrAssign, Shl};
5
6const MSB: u8 = 0x80;
7const REST: u8 = 0x7F;
8pub trait VarInt {
9  fn parse(value: u128) -> Self;
10  fn retrieve(value: Self) -> u128;
11}
12
13impl VarInt for u64 {
14  fn parse(data: u128) -> u64 {
15    return data as u64;
16  }
17  fn retrieve(value: u64) -> u128 {
18    return value as u128;
19  }
20}
21
22impl VarInt for u32 {
23  fn parse(data: u128) -> u32 {
24    return data as u32;
25  }
26  fn retrieve(value: u32) -> u128 {
27    return value as u128;
28  }
29}
30
31impl VarInt for u16 {
32  fn parse(data: u128) -> u16 {
33    return data as u16;
34  }
35  fn retrieve(value: u16) -> u128 {
36    return value as u128;
37  }
38}
39
40impl VarInt for u8 {
41  fn parse(data: u128) -> u8 {
42    return data as u8;
43  }
44  fn retrieve(value: u8) -> u128 {
45    return value as u128;
46  }
47}
48
49pub fn read<T: VarInt, R: Read>(mut reader: R) -> T
50where
51  T: From<u8> + BitAnd + BitOrAssign + Shl + VarInt,
52{
53  let mut temp: u128 = 0;
54  for shift in (0..).step_by(7) {
55    let mut piece = [0];
56    reader.read_exact(&mut piece[..]).expect("Failed to read");
57    temp |= ((piece[0] & REST) as u128) << shift;
58    if (piece[0] & MSB) == 0 {
59      if piece[0] == 0 && shift != 0 {
60        panic!("Read Varint, invalid value representation");
61      }
62      break;
63    }
64  }
65  return T::parse(temp);
66}
67
68pub fn write<T: VarInt, W: Write>(writer: &mut W, value: T)
69where
70  T: From<u8> + BitAnd + BitOrAssign + Shl + VarInt,
71{
72  let mut temp = T::retrieve(value);
73  while temp >= 0x80 {
74    let mut piece = [0];
75    piece[0] = temp as u8 | MSB;
76    writer.write(&piece).expect("Failed to write");
77    temp >>= 7;
78  }
79  let mut piece = [0];
80  piece[0] = temp as u8;
81  writer.write(&piece).expect("Failed to write");
82}
83
84#[cfg(test)]
85mod tests {
86  use super::{read, write};
87  use std::io::{Cursor, Seek, SeekFrom};
88
89  #[test]
90  fn it_should_read() {
91    let data0 = [0x01];
92    assert_eq!(read::<u8, _>(&data0[..]), 1);
93    let data = [0x01];
94    assert_eq!(read::<u16, _>(&data[..]), 1);
95    let data1 = [0xF, 0x00];
96    println!("{}", read::<u32, _>(&data1[..]));
97    assert_eq!(read::<u32, _>(&data1[..]), 15);
98    let data2 = [0x80, 0x1E];
99    assert_eq!(read::<u32, _>(&data2[..]), 0x0F00);
100
101    let data3 = [0x80, 0x1E, 0x11, 0x11, 0x11, 0x11];
102    println!("{}", read::<u64, _>(&data3[..]));
103    assert_eq!(read::<u64, _>(&data3[..]), 3840);
104  }
105
106  #[test]
107  fn it_should_write() {
108    let mut c = Cursor::new(Vec::new());
109    c.seek(SeekFrom::Start(0)).unwrap();
110    write::<u8, _>(&mut c, 1 as u8);
111    let mut c1 = Cursor::new(Vec::new());
112    c1.seek(SeekFrom::Start(0)).unwrap();
113    write::<u16, _>(&mut c1, 128 as u16);
114    let mut c2 = Cursor::new(Vec::new());
115    c2.seek(SeekFrom::Start(0)).unwrap();
116    write::<u32, _>(&mut c2, 129 as u32);
117    let mut c3 = Cursor::new(Vec::new());
118    c3.seek(SeekFrom::Start(0)).unwrap();
119    write::<u64, _>(&mut c3, 0xF1 as u64);
120    let mut c4 = Cursor::new(Vec::new());
121    c4.seek(SeekFrom::Start(0)).unwrap();
122    write::<u64, _>(&mut c4, 300 as u64);
123    let cArr = c.get_ref();
124    assert_eq!(cArr[0], 1);
125
126    let cArr1 = c1.get_ref();
127    assert_eq!(cArr1[0], 128);
128    assert_eq!(cArr1[1], 1);
129    let cArr2 = c2.get_ref();
130    assert_eq!(cArr2[0], 129);
131    assert_eq!(cArr2[1], 1);
132
133    let cArr3 = c3.get_ref();
134    assert_eq!(cArr3[0], 241);
135    assert_eq!(cArr3[1], 1);
136    let cArr4 = c4.get_ref();
137    assert_eq!(cArr4[0], 0xAC);
138    assert_eq!(cArr4[1], 0x02);
139    println!("c = {:?}\n", c.get_ref());
140    println!("c1 = {:?}\n", c1.get_ref());
141    println!("c2 = {:?}\n", c2.get_ref());
142    println!("c3 = {:?}\n", c3.get_ref());
143    println!("c4 = {:?}\n", c4.get_ref());
144  }
145  #[test]
146  #[should_panic]
147  fn it_should_panic_when_read() {
148    let data = [0xFF];
149    read::<u32, _>(&data[..]);
150  }
151}