1pub const WT_VARINT: u32 = 0;
9pub const WT_I64: u32 = 1;
10pub const WT_LEN: u32 = 2;
11pub const WT_START_GROUP: u32 = 3;
12pub const WT_END_GROUP: u32 = 4;
13pub const WT_I32: u32 = 5;
14
15#[derive(Debug)]
28pub struct VarintResult {
29 pub next_pos: usize,
31 pub varint_gar: Option<Vec<u8>>,
33 pub varint: Option<u64>,
35 pub varint_ohb: Option<u64>,
37}
38
39#[inline]
48pub fn parse_varint(buf: &[u8], start: usize) -> VarintResult {
49 let buflen = buf.len();
50 assert!(start <= buflen);
51
52 if start == buflen {
53 return VarintResult {
55 next_pos: start,
56 varint_gar: Some(vec![]),
57 varint: None,
58 varint_ohb: None,
59 };
60 }
61
62 let mut v: u64 = 0;
63 let mut shift: u32 = 0;
64 let mut pos = start;
65 let mut too_big = false;
66
67 loop {
68 if pos >= buflen {
69 return VarintResult {
71 next_pos: buflen,
72 varint_gar: Some(buf[start..].to_vec()),
73 varint: None,
74 varint_ohb: None,
75 };
76 }
77 let b = buf[pos];
78 pos += 1;
79
80 let bits = (b & 0x7f) as u64;
81 if shift < 64 {
82 if shift == 63 && bits > 1 {
85 too_big = true;
86 } else {
87 v |= bits << shift;
88 }
89 } else {
90 if bits != 0 {
92 too_big = true;
93 }
94 }
95 shift += 7;
96
97 if b & 0x80 == 0 {
98 break; }
100
101 if shift > 70 {
102 while pos < buflen {
105 let b2 = buf[pos];
106 pos += 1;
107 if (b2 & 0x7f) != 0 {
108 too_big = true;
109 }
110 if b2 & 0x80 == 0 {
111 break;
112 }
113 }
114 break;
115 }
116 }
117
118 if too_big {
119 return VarintResult {
123 next_pos: buflen,
124 varint_gar: Some(buf[start..].to_vec()),
125 varint: None,
126 varint_ohb: None,
127 };
128 }
129
130 let last_b = buf[pos - 1];
133
134 let ohb = if last_b == 0x00 && pos > start + 1 {
136 let mut count: u64 = 1;
138 let mut p = pos - 2; while p > start && buf[p] == 0x80 {
140 count += 1;
141 p -= 1;
142 }
143 Some(count)
144 } else {
145 None
146 };
147
148 VarintResult {
149 next_pos: pos,
150 varint_gar: None,
151 varint: Some(v),
152 varint_ohb: ohb,
153 }
154}
155
156pub fn encode_varint_bytes(value: u64, ohb: Option<u64>) -> Vec<u8> {
160 let mut out = Vec::new();
161 write_varint_ohb(value, ohb, &mut out);
162 out
163}
164
165#[inline]
174pub fn write_varint_ohb(value: u64, ohb: Option<u64>, out: &mut Vec<u8>) {
175 let mut v = value;
176 loop {
177 let b = (v & 0x7f) as u8;
178 v >>= 7;
179 if v != 0 {
180 out.push(b | 0x80);
181 } else {
182 out.push(b);
183 break;
184 }
185 }
186 if let Some(count) = ohb {
187 if count > 0 {
188 *out.last_mut().unwrap() |= 0x80; for _ in 0..count - 1 {
190 out.push(0x80);
191 }
192 out.push(0x00); }
194 }
195}
196
197#[derive(Debug, Clone)]
208pub struct WiretagResult {
209 pub next_pos: usize,
210 pub wtag_gar: Option<Vec<u8>>,
212 pub wtype: Option<u32>,
214 pub wfield: Option<u64>,
216 pub wfield_ohb: Option<u64>,
218 pub wfield_oor: Option<bool>,
220}
221
222#[inline]
229pub fn parse_wiretag(buf: &[u8], start: usize) -> WiretagResult {
230 let buflen = buf.len();
231 assert!(start < buflen, "parse_wiretag called at end of buffer");
232
233 let first_byte = buf[start];
234 let wtype = (first_byte & 0x07) as u32;
235
236 if wtype > 5 {
237 return WiretagResult {
239 next_pos: buflen,
240 wtag_gar: Some(buf[start..].to_vec()),
241 wtype: None,
242 wfield: None,
243 wfield_ohb: None,
244 wfield_oor: None,
245 };
246 }
247
248 let vr = parse_varint(buf, start);
251
252 if let Some(gar) = vr.varint_gar {
253 return WiretagResult {
255 next_pos: vr.next_pos,
256 wtag_gar: Some(gar),
257 wtype: None,
258 wfield: None,
259 wfield_ohb: None,
260 wfield_oor: None,
261 };
262 }
263
264 let raw = vr.varint.unwrap();
265 let field_number = raw >> 3;
266 let ohb = vr.varint_ohb;
267 let oor = if field_number == 0 || field_number >= (1 << 29) {
268 Some(true)
269 } else {
270 None
271 };
272
273 WiretagResult {
274 next_pos: vr.next_pos,
275 wtag_gar: None,
276 wtype: Some(wtype),
277 wfield: Some(field_number),
278 wfield_ohb: ohb,
279 wfield_oor: oor,
280 }
281}
282
283#[inline]
289pub fn decode_int64(v: u64) -> i64 {
290 v as i64
291}
292
293#[inline]
295pub fn decode_int32(v: u64) -> i32 {
296 (v as u32) as i32
297}
298
299#[inline]
301pub fn decode_uint32(v: u64) -> u32 {
302 v as u32
303}
304
305#[inline]
307pub fn decode_uint64(v: u64) -> u64 {
308 v
309}
310
311#[inline]
313pub fn decode_bool(v: u64) -> bool {
314 v != 0
315}
316
317#[inline]
319pub fn decode_sint32(v: u64) -> i32 {
320 let n = v as u32;
321 ((n >> 1) as i32) ^ -((n & 1) as i32)
322}
323
324#[inline]
326pub fn decode_sint64(v: u64) -> i64 {
327 ((v >> 1) as i64) ^ -((v & 1) as i64)
328}
329
330#[inline]
332pub fn decode_fixed32(data: &[u8]) -> u32 {
333 u32::from_le_bytes(data[..4].try_into().unwrap())
334}
335
336#[inline]
338pub fn decode_sfixed32(data: &[u8]) -> i32 {
339 i32::from_le_bytes(data[..4].try_into().unwrap())
340}
341
342#[inline]
344pub fn decode_float(data: &[u8]) -> f32 {
345 f32::from_le_bytes(data[..4].try_into().unwrap())
346}
347
348#[inline]
350pub fn decode_fixed64(data: &[u8]) -> u64 {
351 u64::from_le_bytes(data[..8].try_into().unwrap())
352}
353
354#[inline]
356pub fn decode_sfixed64(data: &[u8]) -> i64 {
357 i64::from_le_bytes(data[..8].try_into().unwrap())
358}
359
360#[inline]
362pub fn decode_double(data: &[u8]) -> f64 {
363 f64::from_le_bytes(data[..8].try_into().unwrap())
364}
365
366#[inline]
370pub fn write_varint(value: u64, buf: &mut Vec<u8>) {
371 let mut v = value;
372 loop {
373 let b = (v & 0x7f) as u8;
374 v >>= 7;
375 if v != 0 {
376 buf.push(b | 0x80);
377 } else {
378 buf.push(b);
379 break;
380 }
381 }
382}
383
384#[inline]
386pub fn write_tag(field_number: u32, wire_type: u32, buf: &mut Vec<u8>) {
387 write_varint(((field_number as u64) << 3) | (wire_type as u64), buf);
388}
389
390#[inline]
392pub fn write_varint_field(field_number: u32, value: u64, buf: &mut Vec<u8>) {
393 write_tag(field_number, WT_VARINT, buf);
394 write_varint(value, buf);
395}
396
397#[inline]
399pub fn write_bool_field(field_number: u32, value: bool, buf: &mut Vec<u8>) {
400 if value {
401 write_tag(field_number, WT_VARINT, buf);
402 buf.push(1u8);
403 }
404}
405
406#[inline]
408pub fn write_opt_varint_field(field_number: u32, value: Option<u64>, buf: &mut Vec<u8>) {
409 if let Some(v) = value {
410 write_varint_field(field_number, v, buf);
411 }
412}
413
414#[inline]
416pub fn write_len_field(field_number: u32, data: &[u8], buf: &mut Vec<u8>) {
417 write_tag(field_number, WT_LEN, buf);
418 write_varint(data.len() as u64, buf);
419 buf.extend_from_slice(data);
420}
421
422pub fn write_fixed32_field(field_number: u32, value: u32, buf: &mut Vec<u8>) {
424 write_tag(field_number, WT_I32, buf);
425 buf.extend_from_slice(&value.to_le_bytes());
426}
427
428pub fn write_fixed64_field(field_number: u32, value: u64, buf: &mut Vec<u8>) {
430 write_tag(field_number, WT_I64, buf);
431 buf.extend_from_slice(&value.to_le_bytes());
432}
433
434#[cfg(test)]
437mod tests {
438 use super::*;
439
440 #[test]
443 fn varint_zero() {
444 let buf = [0x00u8];
445 let r = parse_varint(&buf, 0);
446 assert_eq!(r.varint, Some(0));
447 assert_eq!(r.varint_ohb, None);
448 assert_eq!(r.next_pos, 1);
449 }
450
451 #[test]
452 fn varint_one_byte() {
453 let buf = [0x01u8];
454 let r = parse_varint(&buf, 0);
455 assert_eq!(r.varint, Some(1));
456 assert_eq!(r.next_pos, 1);
457 }
458
459 #[test]
460 fn varint_150() {
461 let buf = [0x96u8, 0x01];
463 let r = parse_varint(&buf, 0);
464 assert_eq!(r.varint, Some(150));
465 assert_eq!(r.next_pos, 2);
466 assert_eq!(r.varint_ohb, None);
467 }
468
469 #[test]
470 fn varint_max_u64() {
471 let buf = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01];
473 let r = parse_varint(&buf, 0);
474 assert_eq!(r.varint, Some(u64::MAX));
475 assert_eq!(r.next_pos, 10);
476 }
477
478 #[test]
479 fn varint_truncated() {
480 let buf = [0x80u8, 0x80];
482 let r = parse_varint(&buf, 0);
483 assert!(r.varint_gar.is_some());
484 assert!(r.varint.is_none());
485 }
486
487 #[test]
488 fn varint_empty_at_end() {
489 let buf = [0x01u8];
490 let r = parse_varint(&buf, 1); assert!(r.varint_gar.is_some());
492 assert_eq!(r.varint_gar.unwrap(), Vec::<u8>::new());
493 }
494
495 #[test]
496 fn varint_overhang_one() {
497 let buf = [0x80u8, 0x00];
499 let r = parse_varint(&buf, 0);
500 assert_eq!(r.varint, Some(0));
501 assert_eq!(r.varint_ohb, Some(1));
502 }
503
504 #[test]
505 fn varint_overhang_two() {
506 let buf = [0x80u8, 0x80, 0x00];
508 let r = parse_varint(&buf, 0);
509 assert_eq!(r.varint, Some(0));
510 assert_eq!(r.varint_ohb, Some(2));
511 }
512
513 #[test]
514 fn varint_encode_with_overhang() {
515 let bytes = encode_varint_bytes(0, Some(1));
516 assert_eq!(bytes, vec![0x80, 0x00]);
517
518 let bytes2 = encode_varint_bytes(0, Some(2));
519 assert_eq!(bytes2, vec![0x80, 0x80, 0x00]);
520
521 let bytes3 = encode_varint_bytes(150, None);
522 assert_eq!(bytes3, vec![0x96, 0x01]);
523 }
524
525 #[test]
526 fn varint_encode_roundtrip() {
527 for val in [0u64, 1, 127, 128, 300, 16383, 16384, u64::MAX] {
528 let encoded = encode_varint_bytes(val, None);
529 let r = parse_varint(&encoded, 0);
530 assert_eq!(r.varint, Some(val), "roundtrip failed for {val}");
531 assert_eq!(r.next_pos, encoded.len());
532 }
533 }
534
535 #[test]
538 fn wiretag_field1_varint() {
539 let buf = [0x08u8];
541 let r = parse_wiretag(&buf, 0);
542 assert_eq!(r.wtype, Some(0));
543 assert_eq!(r.wfield, Some(1));
544 assert_eq!(r.wfield_ohb, None);
545 assert_eq!(r.wfield_oor, None);
546 }
547
548 #[test]
549 fn wiretag_invalid_wire_type() {
550 let buf = [0x06u8, 0x00, 0x01];
552 let r = parse_wiretag(&buf, 0);
553 assert!(r.wtag_gar.is_some());
554 assert!(r.wtype.is_none());
555 }
556
557 #[test]
558 fn wiretag_field_number_zero_is_oor() {
559 let buf = [0x00u8]; let r = parse_wiretag(&buf, 0);
563 assert_eq!(r.wfield, Some(0));
564 assert_eq!(r.wfield_oor, Some(true));
565 }
566
567 #[test]
568 fn wiretag_overhung() {
569 let buf = [0x88u8, 0x00];
571 let r = parse_wiretag(&buf, 0);
572 assert_eq!(r.wtype, Some(0));
573 assert_eq!(r.wfield, Some(1));
574 assert_eq!(r.wfield_ohb, Some(1));
575 }
576
577 #[test]
580 fn int32_negative() {
581 assert_eq!(decode_int32(0xFFFFFFFF), -1i32);
583 }
584
585 #[test]
586 fn int64_negative() {
587 assert_eq!(decode_int64(u64::MAX), -1i64);
588 }
589
590 #[test]
591 fn sint32_roundtrip() {
592 for v in [-1i32, 0, 1, -2, 2, i32::MIN, i32::MAX] {
593 let encoded = if v >= 0 {
594 ((v as u32) << 1) as u64
595 } else {
596 ((!v as u32) * 2 + 1) as u64
597 };
598 assert_eq!(decode_sint32(encoded), v, "sint32 roundtrip for {v}");
599 }
600 }
601
602 #[test]
603 fn sint64_roundtrip() {
604 for v in [-1i64, 0, 1, -2, 2, i64::MIN, i64::MAX] {
605 let encoded = if v >= 0 {
606 (v as u64) << 1
607 } else {
608 ((!v as u64) << 1) | 1
609 };
610 assert_eq!(decode_sint64(encoded), v, "sint64 roundtrip for {v}");
611 }
612 }
613
614 #[test]
615 fn fixed32_little_endian() {
616 let data = [0x01u8, 0x00, 0x00, 0x00];
617 assert_eq!(decode_fixed32(&data), 1u32);
618 let data2 = [0xFFu8, 0xFF, 0xFF, 0xFF];
619 assert_eq!(decode_fixed32(&data2), u32::MAX);
620 }
621
622 #[test]
623 fn fixed64_little_endian() {
624 let data = [0x01u8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
625 assert_eq!(decode_fixed64(&data), 1u64);
626 }
627
628 #[test]
629 fn double_roundtrip() {
630 let val = std::f64::consts::PI;
631 let data = val.to_le_bytes();
632 assert_eq!(decode_double(&data), val);
633 }
634
635 #[test]
636 fn float_roundtrip() {
637 let val = 1.5f32;
638 let data = val.to_le_bytes();
639 assert_eq!(decode_float(&data), val);
640 }
641
642 #[test]
643 fn write_varint_field_roundtrip() {
644 let mut buf = Vec::new();
645 write_varint_field(1, 300, &mut buf);
646 assert_eq!(buf, vec![0x08, 0xAC, 0x02]);
648 }
649
650 #[test]
651 fn write_len_field_roundtrip() {
652 let mut buf = Vec::new();
653 write_len_field(2, b"hi", &mut buf);
654 assert_eq!(buf, vec![0x12, 0x02, 0x68, 0x69]);
656 }
657}