cashweb_bitcoin/
var_int.rs1use bytes::{Buf, BufMut};
5use thiserror::Error;
6
7use super::{Decodable, Encodable};
8
9#[derive(Clone, Debug, PartialEq, Eq, Error)]
11pub enum DecodeError {
12 #[error("varint too short")]
14 TooShort,
15 #[error("varint non-minimal")]
17 NonMinimal,
18}
19
20#[derive(Clone, Debug, PartialEq)]
22pub struct VarInt(pub u64);
23
24impl Into<u64> for VarInt {
25 fn into(self) -> u64 {
26 self.0
27 }
28}
29
30impl Encodable for VarInt {
31 #[inline]
32 fn encoded_len(&self) -> usize {
33 match self.0 {
34 0..=0xfc => 1,
35 0xfd..=0xffff => 3,
36 0x10000..=0xffffffff => 5,
37 _ => 9,
38 }
39 }
40
41 #[inline]
42 fn encode_raw<B: BufMut>(&self, buf: &mut B) {
43 match self.0 {
44 0..=0xfc => {
45 buf.put_uint_le(self.0, 1);
46 }
47 0xfd..=0xffff => {
48 buf.put_u8(0xfd);
49 buf.put_uint_le(self.0, 2);
50 }
51 0x10000..=0xffffffff => {
52 buf.put_u8(0xfe);
53 buf.put_uint_le(self.0, 4);
54 }
55 _ => {
56 buf.put_u8(0xff);
57 buf.put_u64_le(self.0);
58 }
59 }
60 }
61}
62
63impl Decodable for VarInt {
64 type Error = DecodeError;
65
66 #[inline]
68 fn decode<B: Buf>(buf: &mut B) -> Result<Self, Self::Error> {
69 if !buf.has_remaining() {
70 return Err(Self::Error::TooShort);
71 }
72 let first_byte = buf.get_u8();
73 match first_byte {
74 0xff => {
75 if buf.remaining() < 8 {
76 return Err(Self::Error::TooShort);
77 }
78 let x = buf.get_u64_le();
79 if x < 0x100000000 {
80 Err(Self::Error::NonMinimal)
81 } else {
82 Ok(Self(x))
83 }
84 }
85 0xfe => {
86 if buf.remaining() < 4 {
87 return Err(Self::Error::TooShort);
88 }
89 let x = buf.get_uint_le(4);
90 if x < 0x10000 {
91 Err(Self::Error::NonMinimal)
92 } else {
93 Ok(Self(x))
94 }
95 }
96 0xfd => {
97 if buf.remaining() < 2 {
98 return Err(Self::Error::TooShort);
99 }
100 let x = buf.get_uint_le(2);
101 if x < 0xfd {
102 Err(Self::Error::NonMinimal)
103 } else {
104 Ok(Self(x))
105 }
106 }
107 n => Ok(VarInt(n.into())),
108 }
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
117 fn encode() {
118 let var_int = VarInt(10);
119 let capacity = var_int.encoded_len();
120 let mut raw = Vec::with_capacity(capacity);
121 var_int.encode(&mut raw).unwrap();
122 assert_eq!(raw, vec![10u8]);
123
124 let var_int = VarInt(0xfc);
125 let mut raw = Vec::with_capacity(var_int.encoded_len());
126 var_int.encode_raw(&mut raw);
127 assert_eq!(raw, vec![0xfcu8]);
128
129 let var_int = VarInt(0xfd);
130 let mut raw = Vec::with_capacity(var_int.encoded_len());
131 var_int.encode_raw(&mut raw);
132 assert_eq!(raw, vec![0xfdu8, 0xfd, 0]);
133
134 let var_int = VarInt(0xfff);
135 let mut raw = Vec::with_capacity(var_int.encoded_len());
136 var_int.encode_raw(&mut raw);
137 assert_eq!(raw, vec![0xfdu8, 0xff, 0xf]);
138
139 let var_int = VarInt(0xf0f0f0f);
140 let mut raw = Vec::with_capacity(var_int.encoded_len());
141 var_int.encode_raw(&mut raw);
142 assert_eq!(raw, vec![0xfeu8, 0xf, 0xf, 0xf, 0xf]);
143
144 let var_int = VarInt(0xf0f0f0f0f0e0);
145 let mut raw = Vec::with_capacity(var_int.encoded_len());
146 var_int.encode_raw(&mut raw);
147 assert_eq!(raw, vec![0xffu8, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0, 0]);
148 }
149}