1use std::io::{Read, Write};
2use std::num::TryFromIntError;
3
4use crate::Variable;
5
6#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)]
15pub struct Signed(i128);
16
17impl Signed {
18 pub(crate) fn encode_be_bytes<W: Write, const N: usize>(
19 mut value: [u8; N],
20 mut output: W,
21 ) -> std::io::Result<usize> {
22 let check_bits = if N == 16 {
23 let reserved = value[0] >> 3;
25 match reserved {
26 0 => 0,
27 0b11111 => 0xFF,
28 _ => return Err(std::io::Error::from(std::io::ErrorKind::InvalidData)),
29 }
30 } else if value[0] >> 7 == 0 {
31 0
33 } else {
34 0xff
36 };
37
38 let (total_length, extra_bytes) = value
39 .iter()
40 .enumerate()
41 .find_map(|(index, &byte)| {
42 if byte == check_bits {
43 None
44 } else {
45 let extra_bytes = N - 1 - index;
46 if byte >> 3 == check_bits >> 3 {
47 Some((extra_bytes + 1, extra_bytes))
48 } else {
49 Some((extra_bytes + 2, extra_bytes + 1))
50 }
51 }
52 })
53 .unwrap_or((0, 0));
54 let total_length = total_length.max(1);
55
56 let length_header = if check_bits == 0 {
57 extra_bytes + 2_usize.pow(4)
58 } else {
59 2_usize.pow(4) - extra_bytes - 1
60 };
61
62 let encoded_length_header = (length_header as u8) << 3;
63 if total_length > N {
64 output.write_all(&[encoded_length_header | (check_bits >> 5)])?;
66 output.write_all(&value)?;
67 } else {
68 value[N - total_length] &= 0b111;
70 value[N - total_length] |= encoded_length_header;
72
73 output.write_all(&value[N - total_length..])?;
74 }
75
76 Ok(total_length)
77 }
78
79 pub(crate) fn decode_variable_bytes<R: Read, const N: usize>(
80 mut input: R,
81 ) -> std::io::Result<[u8; N]> {
82 let mut buffer = [0_u8; N];
83 input.read_exact(&mut buffer[0..1])?;
84 let first_byte = buffer[0];
85 let encoded_length = first_byte as usize >> 3;
86 let (negative, length) = if encoded_length >= 2_usize.pow(4) {
87 (false, encoded_length - 2_usize.pow(4))
88 } else {
89 (true, 2_usize.pow(4) - (encoded_length + 1))
90 };
91 if length > N {
92 return Err(std::io::Error::from(std::io::ErrorKind::InvalidData));
93 }
94
95 input.read_exact(&mut buffer[N - length..])?;
96
97 match N - length {
98 0 => {
99 let mut first_bits = first_byte & 0b111;
102 if negative {
103 first_bits ^= 0b111;
104 }
105 buffer[0] |= first_bits << 5;
106 }
107 1 => {
108 buffer[0] &= 0b111;
110 if negative {
111 buffer[0] ^= 0b1111_1000;
112 }
113 }
114 _ => {
115 buffer[N - 1 - length] |= first_byte & 0b111;
116 if negative {
117 buffer[N - 1 - length] ^= 0b1111_1000;
118 }
119 buffer[0] = 0;
120 }
121 }
122
123 if negative && N > 1 {
124 let bytes_to_negate = N - length;
125 if bytes_to_negate > 1 {
127 for byte in &mut buffer[0..bytes_to_negate - 1] {
128 *byte ^= 0xFF;
129 }
130 }
131 }
132
133 Ok(buffer)
134 }
135}
136
137impl Variable for Signed {
138 fn encode_variable<W: Write>(&self, output: W) -> std::io::Result<usize> {
139 Self::encode_be_bytes(self.0.to_be_bytes(), output)
140 }
141
142 fn decode_variable<R: Read>(mut input: R) -> std::io::Result<Self> {
143 let mut buffer = [0_u8; 16];
144 input.read_exact(&mut buffer[0..1])?;
145
146 let encoded_length = buffer[0] as usize >> 3;
147 let (negative, length) = if encoded_length >= 2_usize.pow(4) {
148 (false, encoded_length - 2_usize.pow(4))
149 } else {
150 (true, 2_usize.pow(4) - (encoded_length + 1))
151 };
152
153 input.read_exact(&mut buffer[16 - length..])?;
154
155 if length < 15 {
156 buffer[15 - length] |= buffer[0] & 0b111;
157 if negative {
158 buffer[15 - length] ^= 0b1111_1000;
159 }
160 buffer[0] = 0;
161 } else {
162 buffer[0] &= 0b111;
163 if negative {
164 buffer[0] ^= 0b1111_1000;
165 }
166 }
167
168 if negative {
169 for byte in &mut buffer[0..15 - length] {
170 *byte ^= 0xFF;
171 }
172 }
173
174 Ok(Self(i128::from_be_bytes(buffer)))
175 }
176}
177
178macro_rules! impl_primitive_from_varint {
179 ($ty:ty) => {
180 impl TryFrom<Signed> for $ty {
181 type Error = TryFromIntError;
182
183 fn try_from(value: Signed) -> Result<Self, Self::Error> {
184 value.0.try_into()
185 }
186 }
187 };
188}
189
190macro_rules! impl_varint_from_primitive {
191 ($ty:ty, $dest:ty) => {
192 impl From<$ty> for Signed {
193 fn from(value: $ty) -> Self {
194 Self(<$dest>::from(value))
195 }
196 }
197 };
198}
199
200impl_varint_from_primitive!(i8, i128);
201impl_varint_from_primitive!(i16, i128);
202impl_varint_from_primitive!(i32, i128);
203impl_varint_from_primitive!(i64, i128);
204impl_varint_from_primitive!(i128, i128);
205
206impl_primitive_from_varint!(i8);
207impl_primitive_from_varint!(i16);
208impl_primitive_from_varint!(i32);
209impl_primitive_from_varint!(i64);
210impl_primitive_from_varint!(isize);
211
212impl From<Signed> for i128 {
213 fn from(value: Signed) -> Self {
214 value.0
215 }
216}
217
218impl From<isize> for Signed {
219 fn from(value: isize) -> Self {
220 Self(value as i128)
221 }
222}