1use crate::error::Error;
2use crate::functional::*;
3use crate::io::blocking_impl::*;
4use std::fmt::Debug;
5use std::fmt::Display;
6use std::ops::Deref;
7
8#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
10pub struct VInt64 {
11 pub value: u64,
13 pub is_unknown: bool,
15}
16
17impl Display for VInt64 {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 let encoded = self.as_encoded();
21 if encoded <= 0xFF {
22 write!(f, "0x{:02X}", encoded)
23 } else if encoded <= 0xFFFF {
24 write!(f, "0x{:04X}", encoded)
25 } else if encoded <= 0xFFFFFF {
26 write!(f, "0x{:06X}", encoded)
27 } else if encoded <= 0xFFFFFFFF {
28 write!(f, "0x{:08X}", encoded)
29 } else if encoded <= 0xFFFFFFFFFF {
30 write!(f, "0x{:010X}", encoded)
31 } else if encoded <= 0xFFFFFFFFFFFF {
32 write!(f, "0x{:012X}", encoded)
33 } else if encoded <= 0xFFFFFFFFFFFFFF {
34 write!(f, "0x{:014X}", encoded)
35 } else {
36 write!(f, "0x{:016X}", encoded)
37 }
38 }
39}
40impl Debug for VInt64 {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 let mut t = f.debug_struct("VInt64");
43 if !self.is_unknown {
44 t.field("value", &self.value);
45 } else {
46 t.field("value", &"Unknown");
47 }
48 t.field("memory", &format!("{}", self));
49 t.finish()
50 }
51}
52
53impl Deref for VInt64 {
54 type Target = u64;
55 fn deref(&self) -> &Self::Target {
56 &self.value
57 }
58}
59impl VInt64 {
60 pub const fn from_encoded(enc: u64) -> Self {
62 if enc == 0xFF {
63 Self {
64 value: 127,
65 is_unknown: true,
66 }
67 } else if enc == 0x407F {
68 Self {
69 value: 127,
70 is_unknown: false,
71 }
72 } else {
73 Self {
74 value: enc & (u64::MAX >> (enc.leading_zeros() + 1)),
75 is_unknown: false,
76 }
77 }
78 }
79
80 pub const fn new_unknown() -> Self {
82 Self {
83 value: 127,
84 is_unknown: true,
85 }
86 }
87
88 pub const fn new(value: u64) -> Self {
90 Self {
91 value,
92 is_unknown: false,
93 }
94 }
95
96 pub fn as_encoded(&self) -> u64 {
98 if self.is_unknown {
99 return 0xFF;
100 }
101 if self.value == 127 {
102 return 0x407F;
103 }
104
105 let size = VInt64::encode_size(self.value);
106 let mut sbuf = [0u8; 8];
107 let slice = &mut sbuf[8 - size..];
108 slice.copy_from_slice(&self.value.to_be_bytes()[8 - size..]);
109 slice[0] |= 1u8 << (8 - size);
110 u64::from_be_bytes(sbuf)
111 }
112
113 pub const fn encode_size(value: u64) -> usize {
115 let leading_zeros = value.leading_zeros() as usize;
116 let total_bits = 64 - leading_zeros;
117 if total_bits == 0 {
118 1
119 } else {
120 (total_bits + 6).div_euclid(7)
121 }
122 }
123}
124
125impl ReadFrom for VInt64 {
126 fn read_from<R: std::io::Read>(r: &mut R) -> crate::Result<Self> {
127 let mut first_byte_buf = [0u8; 1];
128 r.read_exact(&mut first_byte_buf)?;
129 let first_byte = first_byte_buf[0];
130 if first_byte == 0xFF {
131 return Ok(VInt64 {
132 value: 127,
133 is_unknown: true,
134 });
135 }
136
137 let leading_zeros = first_byte.leading_zeros() as usize;
138 if leading_zeros >= 8 {
139 return Err(crate::error::Error::InvalidVInt);
140 }
141
142 if leading_zeros == 0 {
143 Ok(VInt64 {
144 value: (first_byte & 0b0111_1111) as u64,
145 is_unknown: false,
146 })
147 } else {
148 let mut buf = [0u8; 8];
149 let read_buf = &mut buf[8 - leading_zeros..];
150 r.read_exact(read_buf)?;
151 if leading_zeros != 7 {
152 buf[8 - leading_zeros - 1] = first_byte & (0xFF >> (leading_zeros + 1));
153 }
154 Ok(VInt64 {
155 value: u64::from_be_bytes(buf),
156 is_unknown: false,
157 })
158 }
159 }
160}
161
162#[cfg(feature = "tokio")]
163#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
164impl crate::io::tokio_impl::AsyncReadFrom for VInt64 {
165 async fn async_read_from<R: tokio::io::AsyncRead + Unpin>(r: &mut R) -> crate::Result<Self> {
166 let mut first_byte_buf = [0u8; 1];
167 tokio::io::AsyncReadExt::read_exact(r, &mut first_byte_buf).await?;
168 let first_byte = first_byte_buf[0];
169 if first_byte == 0xFF {
170 return Ok(VInt64 {
171 value: 127,
172 is_unknown: true,
173 });
174 }
175
176 let leading_zeros = first_byte.leading_zeros() as usize;
177 if leading_zeros >= 8 {
178 return Err(crate::error::Error::InvalidVInt);
179 }
180
181 if leading_zeros == 0 {
182 Ok(VInt64 {
183 value: (first_byte & 0b0111_1111) as u64,
184 is_unknown: false,
185 })
186 } else {
187 let mut buf = [0u8; 8];
188 let read_buf = &mut buf[8 - leading_zeros..];
189 tokio::io::AsyncReadExt::read_exact(r, read_buf).await?;
190 if leading_zeros != 7 {
191 buf[8 - leading_zeros - 1] = first_byte & (0xFF >> (leading_zeros + 1));
192 }
193 Ok(VInt64 {
194 value: u64::from_be_bytes(buf),
195 is_unknown: false,
196 })
197 }
198 }
199}
200
201impl Decode for VInt64 {
202 fn decode(buf: &mut &[u8]) -> crate::Result<Self> {
203 if !buf.has_remaining() {
204 return Err(Error::OutOfBounds);
205 }
206 let first_byte = u8::decode(buf)?;
207 if first_byte == 0 {
208 return Err(Error::InvalidVInt);
209 }
210 if first_byte == 0xFF {
211 return Ok(VInt64 {
212 value: 127,
213 is_unknown: true,
214 });
215 }
216 let leading_zeros = first_byte.leading_zeros() as usize;
217
218 if leading_zeros == 0 {
219 Ok(VInt64 {
220 value: (first_byte & 0b0111_1111) as u64,
221 is_unknown: false,
222 })
223 } else {
224 if buf.remaining() < leading_zeros {
225 return Err(Error::OutOfBounds);
226 }
227 let mut bytes = [0u8; 8];
228 let read_buf = &mut bytes[8 - leading_zeros..];
229 read_buf.copy_from_slice(buf.slice(leading_zeros));
230
231 if leading_zeros != 7 {
232 bytes[8 - leading_zeros - 1] = first_byte & (0xFF >> (leading_zeros + 1));
233 }
234 buf.advance(leading_zeros);
235 Ok(VInt64 {
236 value: u64::from_be_bytes(bytes),
237 is_unknown: false,
238 })
239 }
240 }
241}
242
243impl Encode for VInt64 {
244 fn encode<B: BufMut>(&self, buf: &mut B) -> crate::Result<()> {
245 if self.is_unknown {
246 buf.append_slice(&[0xFF]);
247 return Ok(());
248 }
249 if self.value == 127 {
250 buf.append_slice(&[0x40, 0x7F]);
251 return Ok(());
252 }
253
254 let size = VInt64::encode_size(self.value);
255 let mut sbuf = [0u8; 8];
256 let slice = &mut sbuf[8 - size..];
257 slice.copy_from_slice(&self.value.to_be_bytes()[8 - size..]);
258 slice[0] |= 1u8 << (8 - size);
259 buf.append_slice(slice);
260 Ok(())
261 }
262}
263
264#[cfg(test)]
265mod tests {
266 use crate::functional::{Decode, Encode};
267
268 use super::*;
269 use std::convert::TryInto;
270
271 #[test]
272 fn test_encode_size() {
273 let test_pair = [
274 (vec![0b1000_0000], 0),
275 (vec![0b1000_0001], 1),
276 (vec![0b0100_0000, 0xFF], 0xFF),
277 (vec![0b0100_0001, 0xFF], 0b1_1111_1111),
278 (vec![0b0111_1111, 0xFF], 0b11_1111_1111_1111),
279 (vec![0b0010_0000, 0b0111_1111, 0xFF], 0b111_1111_1111_1111),
280 (vec![0b0010_0000, 0xFF, 0xFF], 0xFFFF),
281 (vec![0b0011_1111, 0xFF, 0xFF], 0b1_1111_1111_1111_1111_1111),
282 (
283 vec![1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
284 0xFF_FFFF_FFFF_FFFF,
285 ),
286 ];
287 for (encoded, val) in test_pair {
288 assert_eq!(VInt64::encode_size(val), encoded.len());
289 }
290 }
291
292 #[test]
293 fn test_encode() {
294 let test_pair = [
295 (vec![0b1000_0000], 0),
296 (vec![0b1000_0001], 1),
297 (vec![0b0100_0000, 0xFF], 0xFF),
298 (vec![0b0100_0001, 0xFF], 0b1_1111_1111),
299 (vec![0b0111_1111, 0xFF], 0b11_1111_1111_1111),
300 (vec![0b0010_0000, 0b0111_1111, 0xFF], 0b111_1111_1111_1111),
301 (vec![0b0010_0000, 0xFF, 0xFF], 0xFFFF),
302 (vec![0b0011_1111, 0xFF, 0xFF], 0b1_1111_1111_1111_1111_1111),
303 (
304 vec![1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
305 0xFF_FFFF_FFFF_FFFF,
306 ),
307 ];
308 for (encoded, val) in test_pair {
309 let v = VInt64 {
310 value: val,
311 is_unknown: false,
312 };
313 let mut out = vec![];
314 v.encode(&mut out).unwrap();
315 assert_eq!(encoded, out);
316
317 let encoded_num = v.as_encoded();
318 let mut enc8 = vec![0u8; 8 - encoded.len()];
319 enc8.extend_from_slice(&encoded);
320 let encoded_from = u64::from_be_bytes(enc8.try_into().unwrap());
321 assert_eq!(encoded_num, encoded_from);
322 }
323 }
324
325 #[test]
326 fn test_decode() {
327 let test_pair = [
328 (vec![0b1000_0000], 0),
329 (vec![0b1000_0001], 1),
330 (vec![0b0100_0000, 0xFF], 0xFF),
331 (vec![0b0100_0001, 0xFF], 0b1_1111_1111),
332 (vec![0b0111_1111, 0xFF], 0b11_1111_1111_1111),
333 (vec![0b0010_0000, 0b0111_1111, 0xFF], 0b111_1111_1111_1111),
334 (vec![0b0010_0000, 0xFF, 0xFF], 0xFFFF),
335 (vec![0b0011_1111, 0xFF, 0xFF], 0b1_1111_1111_1111_1111_1111),
336 (
337 vec![1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
338 0xFF_FFFF_FFFF_FFFF,
339 ),
340 ];
341 for (encoded, val) in test_pair {
342 let mut c = std::io::Cursor::new(encoded.clone());
344 let vint = VInt64::read_from(&mut c).unwrap();
345 assert_eq!(*vint, val);
346
347 let ecoded2 = encoded.clone();
349 let mut slice_encoded2 = &ecoded2[..];
350 let vint_decoded = VInt64::decode(&mut slice_encoded2).unwrap();
351 assert_eq!(*vint_decoded, val);
352
353 let mut enc8 = vec![0u8; 8 - encoded.len()];
355 enc8.extend_from_slice(&encoded);
356 let v = VInt64::from_encoded(u64::from_be_bytes(enc8.try_into().unwrap()));
357 assert_eq!(*v, val);
358 }
359 }
360
361 #[test]
362 fn test_unknown() {
363 let v1 = VInt64::read_from(&mut std::io::Cursor::new(vec![0xFF])).unwrap();
364 let vv1 = VInt64::from_encoded(0xFF);
365 assert!(v1.is_unknown);
366 assert!(vv1.is_unknown);
367
368 let v2 = VInt64::read_from(&mut std::io::Cursor::new(vec![0x80])).unwrap();
369 let vv2 = VInt64::from_encoded(0x80);
370
371 assert!(!v2.is_unknown);
372 assert!(!vv2.is_unknown);
373
374 let v3 = VInt64::read_from(&mut std::io::Cursor::new(vec![0x40, 0x7F])).unwrap();
375 let vv3 = VInt64::from_encoded(0x407F);
376 assert_eq!(*v3, 127);
377 assert_eq!(*vv3, 127);
378
379 assert_ne!(VInt64::new(127), VInt64::new_unknown());
380 assert_eq!(VInt64::new(127).as_encoded(), 0x407F);
381 }
382}
383
384#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
386pub struct Header {
387 pub id: VInt64,
389 pub size: VInt64,
391}
392
393impl ReadFrom for Header {
394 fn read_from<R: std::io::Read>(reader: &mut R) -> crate::Result<Self> {
395 let id = VInt64::read_from(reader)?;
396 let size = VInt64::read_from(reader)?;
397 Ok(Self { id, size })
398 }
399}
400
401#[cfg(feature = "tokio")]
402#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
403impl crate::io::tokio_impl::AsyncReadFrom for Header {
404 async fn async_read_from<R: tokio::io::AsyncRead + Unpin>(r: &mut R) -> crate::Result<Self> {
405 let id = VInt64::async_read_from(r).await?;
406 let size = VInt64::async_read_from(r).await?;
407 Ok(Self { id, size })
408 }
409}
410
411impl Decode for Header {
412 fn decode(buf: &mut &[u8]) -> crate::Result<Self> {
413 let id = VInt64::decode(buf)?;
414 let size = VInt64::decode(buf)?;
415 Ok(Self { id, size })
416 }
417}
418
419impl Encode for Header {
420 fn encode<B: BufMut>(&self, buf: &mut B) -> crate::Result<()> {
421 self.id.encode(buf)?;
422 self.size.encode(buf)?;
423 Ok(())
424 }
425}