1#![allow(clippy::len_zero)]
8#![allow(clippy::from_over_into)]
9
10use super::Error;
11use super::Packable;
12use super::Unpackable;
13
14use std::convert::TryInto;
15
16#[allow(non_camel_case_types)]
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub struct v64 {
24 x: u64,
25}
26
27impl From<u8> for v64 {
28 fn from(x: u8) -> v64 {
29 v64 { x: x as u64 }
30 }
31}
32
33impl TryInto<u8> for v64 {
34 type Error = Error;
35
36 fn try_into(self) -> Result<u8, Error> {
37 match self.x.try_into() {
38 Ok(x) => Ok(x),
39 Err(_) => Err(Error::UnsignedOverflow { value: self.x }),
40 }
41 }
42}
43
44impl From<u16> for v64 {
45 fn from(x: u16) -> v64 {
46 v64 { x: x as u64 }
47 }
48}
49
50impl TryInto<u16> for v64 {
51 type Error = Error;
52
53 fn try_into(self) -> Result<u16, Error> {
54 match self.x.try_into() {
55 Ok(x) => Ok(x),
56 Err(_) => Err(Error::UnsignedOverflow { value: self.x }),
57 }
58 }
59}
60
61impl From<u32> for v64 {
62 fn from(x: u32) -> v64 {
63 v64 { x: x as u64 }
64 }
65}
66
67impl TryInto<u32> for v64 {
68 type Error = Error;
69
70 fn try_into(self) -> Result<u32, Error> {
71 match self.x.try_into() {
72 Ok(x) => Ok(x),
73 Err(_) => Err(Error::UnsignedOverflow { value: self.x }),
74 }
75 }
76}
77
78impl From<u64> for v64 {
79 fn from(x: u64) -> v64 {
80 v64 { x }
81 }
82}
83
84impl Into<u64> for v64 {
85 fn into(self) -> u64 {
86 self.x
87 }
88}
89
90impl From<i8> for v64 {
91 fn from(x: i8) -> v64 {
92 v64 { x: x as u64 }
93 }
94}
95
96impl TryInto<i8> for v64 {
97 type Error = Error;
98
99 fn try_into(self) -> Result<i8, Error> {
100 let value: i64 = self.x as i64;
101 match value.try_into() {
102 Ok(x) => Ok(x),
103 Err(_) => Err(Error::SignedOverflow { value }),
104 }
105 }
106}
107
108impl From<i16> for v64 {
109 fn from(x: i16) -> v64 {
110 v64 { x: x as u64 }
111 }
112}
113
114impl TryInto<i16> for v64 {
115 type Error = Error;
116
117 fn try_into(self) -> Result<i16, Error> {
118 let value: i64 = self.x as i64;
119 match value.try_into() {
120 Ok(x) => Ok(x),
121 Err(_) => Err(Error::SignedOverflow { value }),
122 }
123 }
124}
125
126impl From<i32> for v64 {
127 fn from(x: i32) -> v64 {
128 v64 { x: x as u64 }
129 }
130}
131
132impl TryInto<i32> for v64 {
133 type Error = Error;
134
135 fn try_into(self) -> Result<i32, Error> {
136 let value: i64 = self.x as i64;
137 match value.try_into() {
138 Ok(x) => Ok(x),
139 Err(_) => Err(Error::SignedOverflow { value }),
140 }
141 }
142}
143
144impl From<i64> for v64 {
145 fn from(x: i64) -> v64 {
146 v64 { x: x as u64 }
147 }
148}
149
150impl Into<i64> for v64 {
151 fn into(self) -> i64 {
152 self.x as i64
153 }
154}
155
156impl From<usize> for v64 {
157 fn from(x: usize) -> v64 {
158 let x: u64 = x.try_into().unwrap();
160 v64 { x }
161 }
162}
163
164impl Into<usize> for v64 {
165 fn into(self) -> usize {
166 let x: usize = self.x.try_into().unwrap();
168 x
169 }
170}
171
172impl Packable for v64 {
173 fn pack_sz(&self) -> usize {
174 let mut x: u64 = self.x;
175 let mut count: usize = 1;
176 x >>= 7;
177 while x > 0 {
178 x >>= 7;
179 count += 1;
180 }
181 count
182 }
183
184 fn pack(&self, out: &mut [u8]) {
185 let mut x: u64 = self.x;
186 out[0] = (x & 0x7f) as u8;
187 x >>= 7;
188 let mut idx: usize = 1;
189 while x > 0 {
190 out[idx - 1] |= 128;
191 out[idx] = (x & 0x7f) as u8;
192 idx += 1;
193 x >>= 7;
194 }
195 }
196}
197
198impl v64 {
199 fn unpack_slow(buf: &[u8]) -> Result<(Self, &[u8]), Error> {
200 let bytes: usize = if buf.len() < 10 { buf.len() } else { 10 };
201 let mut ret = 0u64;
202 let mut idx = 0;
203 let mut shl = 0;
204 while idx + 1 < bytes && buf[idx] & 128 != 0 {
205 ret |= (buf[idx] as u64 & 127) << shl;
206 idx += 1;
207 shl += 7;
208 }
209 if !buf.is_empty() && buf[idx] & 128 == 0 {
210 ret |= (buf[idx] as u64 & 127) << shl;
211 idx += 1;
212 let ret: v64 = ret.into();
213 Ok((ret, &buf[idx..]))
214 } else {
215 Err(Error::VarintOverflow { bytes })
216 }
217 }
218
219 fn unpack_size<const SZ: usize>(buf: &[u8]) -> Result<(Self, &[u8]), Error> {
220 let mut result = (buf[SZ - 1] as u64) << (7 * (SZ - 1));
221 let mut offset = 0;
222 for b in buf.iter().take(SZ - 1) {
223 result += (*b as u64 - 0x80) << offset;
224 offset += 7;
225 }
226 Ok((v64::from(result), &buf[SZ..]))
227 }
228}
229
230impl<'a> Unpackable<'a> for v64 {
231 type Error = Error;
232
233 #[inline(always)]
234 fn unpack<'b>(buf: &'b [u8]) -> Result<(Self, &'b [u8]), Error>
235 where
236 'b: 'a,
237 {
238 if buf.len() < 10 {
239 return Self::unpack_slow(buf);
240 }
241 if buf[0] < 128 {
242 Self::unpack_size::<1>(buf)
243 } else if buf[1] < 128 {
244 Self::unpack_size::<2>(buf)
245 } else if buf[2] < 128 {
246 Self::unpack_size::<3>(buf)
247 } else if buf[3] < 128 {
248 Self::unpack_size::<4>(buf)
249 } else if buf[4] < 128 {
250 Self::unpack_size::<5>(buf)
251 } else if buf[5] < 128 {
252 Self::unpack_size::<6>(buf)
253 } else if buf[6] < 128 {
254 Self::unpack_size::<7>(buf)
255 } else if buf[7] < 128 {
256 Self::unpack_size::<8>(buf)
257 } else if buf[8] < 128 {
258 Self::unpack_size::<9>(buf)
259 } else if buf[9] < 128 {
260 Self::unpack_size::<10>(buf)
261 } else {
262 Err(Error::VarintOverflow { bytes: buf.len() })
263 }
264 }
265}
266
267#[cfg(test)]
270mod tests {
271 use super::*;
272
273 fn from_into_x<X, E>(x: X)
274 where
275 v64: std::convert::From<X> + std::convert::TryInto<X, Error = E>,
276 X: std::fmt::Debug + PartialEq + Copy,
277 E: std::fmt::Debug,
278 {
279 let v: v64 = v64::from(x);
280 let x2: X = v.try_into().unwrap();
281 assert_eq!(x, x2, "value did not survive a .into().into()");
282 }
283
284 #[test]
285 fn from_into_u8() {
286 from_into_x(u8::MIN);
287 from_into_x(u8::MAX);
288 from_into_x(1u8);
289 }
290
291 #[test]
292 fn try_into_u8() {
293 let x: u64 = (u8::MAX as u64) + 1;
294 let v: v64 = v64::from(x);
295 let x2: Result<u8, Error> = v.try_into();
296 assert_eq!(Err(Error::UnsignedOverflow { value: x }), x2);
297 }
298
299 #[test]
300 fn from_into_u16() {
301 from_into_x(u16::MIN);
302 from_into_x(u16::MAX);
303 from_into_x(1u16);
304 }
305
306 #[test]
307 fn try_into_u16() {
308 let x: u64 = (u16::MAX as u64) + 1;
309 let v: v64 = v64::from(x);
310 let x2: Result<u16, Error> = v.try_into();
311 assert_eq!(Err(Error::UnsignedOverflow { value: x }), x2);
312 }
313
314 #[test]
315 fn from_into_u32() {
316 from_into_x(u32::MIN);
317 from_into_x(u32::MAX);
318 from_into_x(1u32);
319 }
320
321 #[test]
322 fn try_into_u32() {
323 let x: u64 = (u32::MAX as u64) + 1;
324 let v: v64 = v64::from(x);
325 let x2: Result<u32, Error> = v.try_into();
326 assert_eq!(Err(Error::UnsignedOverflow { value: x }), x2);
327 }
328
329 #[test]
330 fn from_into_u64() {
331 from_into_x(u64::MIN);
332 from_into_x(u64::MAX);
333 from_into_x(1u64);
334 }
335
336 #[test]
337 fn from_into_i8() {
338 from_into_x(i8::MIN);
339 from_into_x(i8::MAX);
340 from_into_x(-1i8);
341 from_into_x(0i8);
342 from_into_x(1i8);
343 }
344
345 #[test]
346 fn try_into_i8() {
347 let x: i64 = (i8::MAX as i64) + 1;
348 let v: v64 = v64::from(x);
349 let x2: Result<i8, Error> = v.try_into();
350 assert_eq!(Err(Error::SignedOverflow { value: x }), x2);
351 }
352
353 #[test]
354 fn from_into_i16() {
355 from_into_x(i16::MIN);
356 from_into_x(i16::MAX);
357 from_into_x(-1i16);
358 from_into_x(0i16);
359 from_into_x(1i16);
360 }
361
362 #[test]
363 fn try_into_i16() {
364 let x: i64 = (i16::MAX as i64) + 1;
365 let v: v64 = v64::from(x);
366 let x2: Result<i16, Error> = v.try_into();
367 assert_eq!(Err(Error::SignedOverflow { value: x }), x2);
368 }
369
370 #[test]
371 fn from_into_i32() {
372 from_into_x(i32::MIN);
373 from_into_x(i32::MAX);
374 from_into_x(-1i32);
375 from_into_x(0i32);
376 from_into_x(1i32);
377 }
378
379 #[test]
380 fn try_into_i32() {
381 let x: i64 = (i32::MAX as i64) + 1;
382 let v: v64 = v64::from(x);
383 let x2: Result<i32, Error> = v.try_into();
384 assert_eq!(Err(Error::SignedOverflow { value: x }), x2);
385 }
386
387 #[test]
388 fn from_into_i64() {
389 from_into_x(i64::MIN);
390 from_into_x(i64::MAX);
391 from_into_x(-1i64);
392 from_into_x(0i64);
393 from_into_x(1i64);
394 }
395
396 #[test]
397 fn from_into_usize() {
398 from_into_x(usize::MIN);
399 from_into_x(usize::MAX);
400 from_into_x(1usize);
401 }
402
403 #[test]
404 fn assumption_u64_holds_usize() {
405 let min: u64 = usize::MIN.try_into().unwrap();
406 let min: usize = min.try_into().unwrap();
407 assert_eq!(usize::MIN, min, "u64 cannot hold usize::MIN");
408 let max: u64 = usize::MAX.try_into().unwrap();
409 let max: usize = max.try_into().unwrap();
410 assert_eq!(usize::MAX, max, "u64 cannot hold usize::MAX");
411 }
412
413 const TESTS: &[(u64, usize, &[u8])] = &[
414 (0, 1, &[0]),
415 (1, 1, &[1]),
416 ((1 << 7) - 1, 1, &[127]),
417 ((1 << 7), 2, &[128, 1]),
418 ((1 << 14) - 1, 2, &[255, 127]),
419 ((1 << 14), 3, &[128, 128, 1]),
420 ((1 << 21) - 1, 3, &[255, 255, 127]),
421 ((1 << 21), 4, &[128, 128, 128, 1]),
422 ((1 << 28) - 1, 4, &[255, 255, 255, 127]),
423 ((1 << 28), 5, &[128, 128, 128, 128, 1]),
424 ((1 << 35) - 1, 5, &[255, 255, 255, 255, 127]),
425 ((1 << 35), 6, &[128, 128, 128, 128, 128, 1]),
426 ((1 << 42) - 1, 6, &[255, 255, 255, 255, 255, 127]),
427 ((1 << 42), 7, &[128, 128, 128, 128, 128, 128, 1]),
428 ((1 << 49) - 1, 7, &[255, 255, 255, 255, 255, 255, 127]),
429 ((1 << 49), 8, &[128, 128, 128, 128, 128, 128, 128, 1]),
430 ((1 << 56) - 1, 8, &[255, 255, 255, 255, 255, 255, 255, 127]),
431 ((1 << 56), 9, &[128, 128, 128, 128, 128, 128, 128, 128, 1]),
432 (
433 (1 << 63) - 1,
434 9,
435 &[255, 255, 255, 255, 255, 255, 255, 255, 127],
436 ),
437 (
438 (1 << 63),
439 10,
440 &[128, 128, 128, 128, 128, 128, 128, 128, 128, 1],
441 ),
442 ];
443
444 #[test]
445 fn pack_varint() {
446 for (idx, &(num, bytes, enc)) in TESTS.iter().enumerate() {
447 println!("test case={idx} x={num}, |x|={bytes}, s(x)={enc:?}");
448 let mut buf: [u8; 10] = [0; 10];
449 assert_eq!(bytes, enc.len(), "human got test case wrong?");
450 assert!(bytes <= buf.len(), "human made buffer too small?");
451 let num: v64 = num.into();
452 let req = num.pack_sz();
453 assert_eq!(bytes, req, "human got pack_sz wrong?");
454 num.pack(&mut buf[..bytes]);
455 assert_eq!(enc, &buf[..bytes], "human got encoder wrong?");
456 }
457 }
458
459 #[test]
460 fn unpack_varint() {
461 for (idx, &(num, bytes, enc)) in TESTS.iter().enumerate() {
462 println!("test case={idx} x={num}, |x|={bytes}, s(x)={enc:?}");
463 assert_eq!(bytes, enc.len(), "human got test case wrong?");
464 assert!(enc.len() <= 10, "human got test harness wrong?");
465 let mut buf: [u8; 10] = [0xff; 10];
466 buf[..enc.len()].copy_from_slice(enc);
467 let (x, rem): (v64, &[u8]) = Unpackable::unpack(&buf).unwrap();
468 let v: v64 = num.into();
469 assert_eq!(v, x, "human got decode wrong?");
470 assert_eq!(rem, &buf[bytes..], "human got remainder wrong?");
471 }
472 }
473
474 }