varinteger/
lib.rs

1#![cfg_attr(feature = "nightly", deny(missing_docs))]
2#![cfg_attr(feature = "nightly", feature(external_doc))]
3#![cfg_attr(feature = "nightly", doc(include = "../README.md"))]
4#![cfg_attr(test, deny(warnings))]
5
6/// Returns how many bytes are needed to encode a value.
7#[inline]
8pub fn length(value: u64) -> usize {
9  let zero_len = 64 - value.leading_zeros();
10  let offset = if zero_len == 0 { 7 } else { 6 };
11  ((offset + zero_len) / 7) as usize
12}
13
14/// Encode a `u64` integer to the byte slice. Returns how many bytes were
15/// encoded.
16#[inline]
17pub fn encode(value: u64, buf: &mut [u8]) -> usize {
18  encode_with_offset(value, buf, 0)
19}
20
21/// Encode a `u64` integer at a specific offset in the byte slice. Returns how
22/// many bytes were encoded.
23#[inline]
24pub fn encode_with_offset(value: u64, buf: &mut [u8], offset: usize) -> usize {
25  let mut off = offset;
26  let mut val = value;
27
28  while val > 127 {
29    buf[off] = (val as u8) | 128;
30    off += 1;
31    val >>= 7;
32  }
33  buf[off] = val as u8;
34
35  off + 1 - offset
36}
37
38/// Decode a byte slice into a `u64` integer. Returns how many bytes were
39/// decoded.
40#[inline]
41pub fn decode(buf: &[u8], value: &mut u64) -> usize {
42  decode_with_offset(buf, 0, value)
43}
44
45/// Decode a byte slice into a `u64` integer at a specific offset. Returns how
46/// many bytes were decoded.
47#[inline]
48pub fn decode_with_offset(buf: &[u8], offset: usize, value: &mut u64) -> usize {
49  let mut val = 0 as u64;
50  let mut fac = 1 as u64;
51  let mut off = offset;
52
53  loop {
54    let byte = buf[off];
55    off += 1;
56    val += fac * ((byte & 127) as u64);
57    fac <<= 7;
58    if byte & 128 == 0 {
59      break;
60    }
61  }
62
63  *value = val;
64
65  off - offset
66}
67
68/// Returns how many bytes are needed to encode a value.
69#[inline]
70pub fn signed_length(value: i64) -> usize {
71  length(unsign(value))
72}
73
74/// Encode a `i64` (signed) integer at a specific offset in the byte slice.
75/// Returns how many bytes were encoded.
76#[inline]
77pub fn signed_encode(value: i64, buf: &mut [u8]) -> usize {
78  encode_with_offset(unsign(value), buf, 0)
79}
80
81/// Encode a `i64` (signed) integer at a specific offset in the byte slice.
82/// Returns how many bytes were encoded.
83#[inline]
84pub fn signed_encode_with_offset(
85  value: i64,
86  buf: &mut [u8],
87  offset: usize,
88) -> usize {
89  encode_with_offset(unsign(value), buf, offset)
90}
91
92/// Decode a byte slice into a `i64` (signed) integer.  Returns how many bytes
93/// were decoded.
94#[inline]
95pub fn signed_decode(buf: &[u8], value: &mut i64) -> usize {
96  signed_decode_with_offset(buf, 0, value)
97}
98
99/// Decode a byte slice into a `i64` (signed) integer at a specific offset.
100/// Returns how many bytes were decoded.
101#[inline]
102pub fn signed_decode_with_offset(
103  buf: &[u8],
104  offset: usize,
105  value: &mut i64,
106) -> usize {
107  let mut val = 0;
108  let off = decode_with_offset(buf, offset, &mut val);
109  *value = sign(val);
110  off
111}
112
113/// Convert an `i64` into a `u64`.
114#[inline]
115fn unsign(value: i64) -> u64 {
116  if value >= 0 {
117    (value * 2) as u64
118  } else {
119    (value * -2 - 1) as u64
120  }
121}
122
123/// Convert a `u64` into a `i64`.
124#[inline]
125fn sign(value: u64) -> i64 {
126  if value & 1 != 0 {
127    -(((value + 1) / 2) as i64)
128  } else {
129    (value / 2) as i64
130  }
131}