1use crate::serializer::{
2 Packer,
3 Encoder,
4};
5
6use crate::print::{
7 Printable,
8 printi,
9};
10
11use crate::vmapi::eosio::{
12 check,
13};
14
15#[cfg_attr(feature = "std", derive(crate::eosio_scale_info::TypeInfo))]
17#[derive(Copy, Clone, Eq, PartialEq, Default, Debug)]
18pub struct VarUint32 {
19 pub n: u32,
21}
22
23impl VarUint32 {
24 pub fn new(n: u32) -> Self {
26 Self { n: n }
27 }
28
29 pub fn value(&self) -> u32 {
31 return self.n;
32 }
33}
34
35impl Packer for VarUint32 {
36 fn size(&self) -> usize {
38 let mut size: usize = 0;
39 let mut val = self.n;
40 if val == 0 {
41 return 1;
42 }
43
44 while val > 0 {
45 val >>= 7;
46 size += 1;
47 }
48 return size;
49 }
50
51 fn pack(&self, enc: &mut Encoder) -> usize {
53 let mut val = self.n;
54 if val == 0 {
55 return 0u8.pack(enc);
56 }
57
58 let mut size = 0usize;
59
60 while val > 0 {
61 let mut b: u32 = val & 0x7f;
62 val >>= 7;
63 if val > 0 {
64 b |= 1 << 7;
65 }
66 let data = enc.alloc(1);
67 data[0] = b as u8;
68 size += 1;
69 }
70 size
71 }
72
73 fn unpack(&mut self, data: &[u8]) -> usize {
75 let mut by: u32 = 0;
76 let mut value: u32 = 0;
77 let mut length: usize = 0;
78 for b in data {
79 value |= (*b as u32 & 0x7f) << by;
80 by += 7;
81 length += 1;
82 if (*b & 0x80) == 0 {
83 break;
84 }
85 check(by < 32, "malformed varuint32 data");
86 }
87 self.n = value;
88 return length;
89 }
90}
91
92impl Printable for VarUint32 {
93 fn print(&self) {
95 printi(self.n as i64);
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn test_varuint32_pack_unpack() {
105 let values = vec![
106 0,
107 1,
108 127,
109 128,
110 255,
111 256,
112 16383,
113 16384,
114 2097151,
115 2097152,
116 268435455,
117 268435456,
118 u32::MAX,
119 ];
120
121 for value in values {
122 let varuint32 = VarUint32::new(value);
123 let mut encoder = Encoder::new(varuint32.size());
124 varuint32.pack(&mut encoder);
125
126 let mut unpacked_varuint32 = VarUint32::default();
127 let _ = unpacked_varuint32.unpack(encoder.get_bytes());
128
129 assert_eq!(varuint32, unpacked_varuint32);
130 }
131 }
132}