bsv_wasm/traits/
varint.rs1use byteorder::LittleEndian;
2use byteorder::ReadBytesExt;
3use byteorder::WriteBytesExt;
4use std::io::Cursor;
5use std::io::Result;
6
7use crate::OpCodes;
8
9pub trait VarIntReader {
10 fn read_varint(&mut self) -> Result<u64>;
11}
12
13pub trait VarIntWriter {
14 fn write_varint(&mut self, varint: u64) -> std::io::Result<usize>;
15}
16
17pub struct VarInt {}
18
19impl VarInt {
20 pub fn get_varint_size(data_length: u64) -> usize {
21 if data_length <= 252 {
22 1
23 } else if data_length <= 0xffff {
24 2
25 } else if data_length <= 0xffffffff {
26 4
27 } else {
28 8
29 }
30 }
31
32 pub fn get_pushdata_opcode(length: u64) -> Option<OpCodes> {
33 if length <= 0x4b {
34 None
35 } else if length <= 0xff {
36 Some(OpCodes::OP_PUSHDATA1)
37 } else if length <= 0xffff {
38 Some(OpCodes::OP_PUSHDATA2)
39 } else {
40 Some(OpCodes::OP_PUSHDATA4)
41 }
42 }
43
44 pub fn get_varint_bytes(length: u64) -> Vec<u8> {
45 if length <= 252 {
46 vec![length as u8]
47 } else if length <= 0xff {
48 let mut push1 = vec![0xfd];
49 push1.extend((length as u16).to_le_bytes());
50 push1
51 } else if length <= 0xffff {
52 let mut push2 = vec![0xfe];
53 push2.extend((length as u32).to_le_bytes());
54 push2
55 } else {
56 let mut push4 = vec![0xff];
57 push4.extend((length as u64).to_le_bytes());
58 push4
59 }
60 }
61}
62
63impl VarIntReader for Cursor<Vec<u8>> {
64 fn read_varint(&mut self) -> Result<u64> {
65 match self.read_u8() {
66 Ok(0xff) => self.read_u64::<LittleEndian>(),
67 Ok(0xfe) => self.read_u32::<LittleEndian>().map(|x| x as u64),
68 Ok(0xfd) => self.read_u16::<LittleEndian>().map(|x| x as u64),
69 Ok(v) => Ok(v as u64),
70 Err(e) => Err(e),
71 }
72 }
73}
74
75impl VarIntWriter for Cursor<Vec<u8>> {
76 fn write_varint(&mut self, varint: u64) -> Result<usize> {
80 let mut write = || {
81 if varint <= 252 {
82 self.write_u8(varint as u8)
83 } else if varint <= 0xffff {
84 self.write_u8(0xfd).and_then(|_| self.write_u16::<LittleEndian>(varint as u16))
85 } else if varint <= 0xffffffff {
86 self.write_u8(0xfe).and_then(|_| self.write_u32::<LittleEndian>(varint as u32))
87 } else {
88 self.write_u8(0xff).and_then(|_| self.write_u64::<LittleEndian>(varint))
89 }
90 };
91
92 write()?;
93 Ok(varint as usize)
94 }
95}
96
97impl VarIntReader for Vec<u8> {
98 fn read_varint(&mut self) -> Result<u64> {
99 let mut cursor = Cursor::new(&self);
100
101 match cursor.read_u8() {
102 Ok(0xff) => cursor.read_u64::<LittleEndian>(),
103 Ok(0xfe) => cursor.read_u32::<LittleEndian>().map(|x| x as u64),
104 Ok(0xfd) => cursor.read_u16::<LittleEndian>().map(|x| x as u64),
105 Ok(v) => Ok(v as u64),
106 Err(e) => Err(e),
107 }
108 }
109}
110
111impl VarIntWriter for Vec<u8> {
112 fn write_varint(&mut self, varint: u64) -> Result<usize> {
116 let mut write = || {
117 if varint <= 252 {
118 self.write_u8(varint as u8)
119 } else if varint <= 0xffff {
120 self.write_u8(0xfd).and_then(|_| self.write_u16::<LittleEndian>(varint as u16))
121 } else if varint <= 0xffffffff {
122 self.write_u8(0xfe).and_then(|_| self.write_u32::<LittleEndian>(varint as u32))
123 } else {
124 self.write_u8(0xff).and_then(|_| self.write_u64::<LittleEndian>(varint))
125 }
126 };
127
128 write()?;
129 Ok(varint as usize)
130 }
131}
132
133impl VarIntReader for Cursor<&'_ [u8]> {
134 fn read_varint(&mut self) -> Result<u64> {
135 match self.read_u8() {
136 Ok(0xff) => self.read_u64::<LittleEndian>(),
137 Ok(0xfe) => self.read_u32::<LittleEndian>().map(|x| x as u64),
138 Ok(0xfd) => self.read_u16::<LittleEndian>().map(|x| x as u64),
139 Ok(v) => Ok(v as u64),
140 Err(e) => Err(e),
141 }
142 }
143}