1use core::fmt;
2
3use crate::decode::{Decode, DecodeError};
4use crate::encode::Encode;
5
6#[repr(transparent)]
22#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
23pub struct VarU16 {
24 inner: u16,
25}
26
27impl VarU16 {
28 pub fn new(value: u16) -> Self {
35 Self::try_new(value).expect("Value too large for variable-length u16")
36 }
37
38 pub const fn try_new(value: u16) -> Result<Self, VarU16SizeError> {
45 if value > (u16::MAX >> 1) {
46 Err(VarU16SizeError { value })
47 } else {
48 Ok(Self { inner: value })
49 }
50 }
51
52 pub fn into_inner(self) -> u16 {
54 self.inner
55 }
56
57 pub fn check_wide(first: u8) -> bool {
59 first > (u8::MAX >> 1) as _
60 }
61}
62
63impl Encode for VarU16 {
64 fn size(&self) -> usize {
65 if self.inner > (u8::MAX >> 1) as _ {
66 2
67 } else {
68 1
69 }
70 }
71
72 fn encode(&self, data: &mut [u8]) {
73 if self.inner > (u8::MAX >> 1) as _ {
74 data[0] = (self.inner >> 8) as u8 | 0x80;
75 data[1] = (self.inner & u8::MAX as u16) as u8;
76 } else {
77 data[0] = self.inner as u8;
78 }
79 }
80}
81
82impl Decode for VarU16 {
83 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
84 let first = u8::decode(data)?;
85 let wide = first & (1 << 7) != 0;
86
87 Ok(Self {
88 inner: if wide {
89 let last = u8::decode(data)?;
90 let both = [first & u8::MAX >> 1, last];
91 u16::from_be_bytes(both)
92 } else {
93 first as u16
94 },
95 })
96 }
97}
98
99#[derive(Clone, PartialEq, Eq, Debug)]
101pub struct VarU16SizeError {
102 pub value: u16,
103}
104
105impl fmt::Display for VarU16SizeError {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 write!(
108 f,
109 "value {} cannot fit in a variable-length u16",
110 self.value
111 )
112 }
113}
114
115impl core::error::Error for VarU16SizeError {
116 fn description(&self) -> &str {
117 "value too large for variable-length u16"
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use crate::{decode::Decode, encode::Encode, varint::VarU16};
124
125 #[test]
126 fn wide() {
127 const VAL: u16 = 0xF00;
129 const EXPECTED_ENCODING: [u8; 2] = [0x8f, 0x00];
130
131 let mut buf = [0; 2];
132
133 let var = VarU16::new(VAL);
134 var.encode(&mut buf);
135
136 assert_eq!(EXPECTED_ENCODING, buf);
137 assert_eq!(
138 VAL,
139 VarU16::decode(&mut EXPECTED_ENCODING.as_slice())
140 .unwrap()
141 .into_inner()
142 )
143 }
144
145 #[test]
146 fn thin() {
147 const VAL: u16 = 0x0F;
149 const EXPECTED_ENCODING: [u8; 1] = [0x0F];
150
151 let mut buf = [0; 1];
152
153 let var = VarU16::new(VAL);
154 var.encode(&mut buf);
155
156 assert_eq!(EXPECTED_ENCODING, buf);
157 assert_eq!(
158 VAL,
159 VarU16::decode(&mut EXPECTED_ENCODING.as_slice())
160 .unwrap()
161 .into_inner()
162 )
163 }
164}