/rust/registry/src/index.crates.io-1949cf8c6b5b557f/protobuf-3.7.2/src/varint/encode.rs
Line | Count | Source |
1 | | use std::mem::MaybeUninit; |
2 | | |
3 | | use crate::varint::MAX_VARINT_ENCODED_LEN; |
4 | | |
5 | | /// Encode u64 as varint. |
6 | | /// Panics if buffer length is less than 10. |
7 | | #[inline] |
8 | 0 | pub(crate) fn encode_varint64(mut value: u64, buf: &mut [MaybeUninit<u8>]) -> usize { |
9 | 0 | assert!(buf.len() >= MAX_VARINT_ENCODED_LEN); |
10 | | |
11 | 0 | fn iter(value: &mut u64, byte: &mut MaybeUninit<u8>) -> bool { |
12 | 0 | if (*value & !0x7F) > 0 { |
13 | 0 | byte.write(((*value & 0x7F) | 0x80) as u8); |
14 | 0 | *value >>= 7; |
15 | 0 | true |
16 | | } else { |
17 | 0 | byte.write(*value as u8); |
18 | 0 | false |
19 | | } |
20 | 0 | } |
21 | | |
22 | | // Explicitly unroll loop to avoid either |
23 | | // unsafe code or bound checking when writing to `buf` |
24 | | |
25 | 0 | if !iter(&mut value, &mut buf[0]) { |
26 | 0 | return 1; |
27 | 0 | }; |
28 | 0 | if !iter(&mut value, &mut buf[1]) { |
29 | 0 | return 2; |
30 | 0 | }; |
31 | 0 | if !iter(&mut value, &mut buf[2]) { |
32 | 0 | return 3; |
33 | 0 | }; |
34 | 0 | if !iter(&mut value, &mut buf[3]) { |
35 | 0 | return 4; |
36 | 0 | }; |
37 | 0 | if !iter(&mut value, &mut buf[4]) { |
38 | 0 | return 5; |
39 | 0 | }; |
40 | 0 | if !iter(&mut value, &mut buf[5]) { |
41 | 0 | return 6; |
42 | 0 | }; |
43 | 0 | if !iter(&mut value, &mut buf[6]) { |
44 | 0 | return 7; |
45 | 0 | }; |
46 | 0 | if !iter(&mut value, &mut buf[7]) { |
47 | 0 | return 8; |
48 | 0 | }; |
49 | 0 | if !iter(&mut value, &mut buf[8]) { |
50 | 0 | return 9; |
51 | 0 | }; |
52 | 0 | buf[9].write(value as u8); |
53 | 0 | 10 |
54 | 0 | } |
55 | | |
56 | | /// Encode u32 value as varint. |
57 | | /// Panics if buffer length is less than 5. |
58 | | #[inline] |
59 | 0 | pub(crate) fn encode_varint32(mut value: u32, buf: &mut [MaybeUninit<u8>]) -> usize { |
60 | 0 | assert!(buf.len() >= 5); |
61 | | |
62 | 0 | fn iter(value: &mut u32, byte: &mut MaybeUninit<u8>) -> bool { |
63 | 0 | if (*value & !0x7F) > 0 { |
64 | 0 | byte.write(((*value & 0x7F) | 0x80) as u8); |
65 | 0 | *value >>= 7; |
66 | 0 | true |
67 | | } else { |
68 | 0 | byte.write(*value as u8); |
69 | 0 | false |
70 | | } |
71 | 0 | } |
72 | | |
73 | | // Explicitly unroll loop to avoid either |
74 | | // unsafe code or bound checking when writing to `buf` |
75 | | |
76 | 0 | if !iter(&mut value, &mut buf[0]) { |
77 | 0 | return 1; |
78 | 0 | }; |
79 | 0 | if !iter(&mut value, &mut buf[1]) { |
80 | 0 | return 2; |
81 | 0 | }; |
82 | 0 | if !iter(&mut value, &mut buf[2]) { |
83 | 0 | return 3; |
84 | 0 | }; |
85 | 0 | if !iter(&mut value, &mut buf[3]) { |
86 | 0 | return 4; |
87 | 0 | }; |
88 | 0 | buf[4].write(value as u8); |
89 | 0 | 5 |
90 | 0 | } |
91 | | |
92 | | /// Encoded size of u64 value. |
93 | | #[inline] |
94 | 0 | pub(crate) fn encoded_varint64_len(value: u64) -> usize { |
95 | | // Bitwise-or'ing by 1 allows the `value = zero` case to work without |
96 | | // affecting other cases. |
97 | 0 | let significant_bits = 64 - (value | 1).leading_zeros(); |
98 | 0 | (significant_bits + 6) as usize / 7 |
99 | 0 | } Unexecuted instantiation: protobuf::varint::encode::encoded_varint64_len Unexecuted instantiation: protobuf::varint::encode::encoded_varint64_len |
100 | | |
101 | | #[cfg(test)] |
102 | | mod test { |
103 | | use std::mem::MaybeUninit; |
104 | | |
105 | | use crate::varint::encode::encode_varint64; |
106 | | use crate::varint::encode::encoded_varint64_len; |
107 | | |
108 | | #[test] |
109 | | fn test_encoded_varint64_len() { |
110 | | fn test(n: u64) { |
111 | | let mut buf = [MaybeUninit::uninit(); 10]; |
112 | | let expected = encode_varint64(n, &mut buf); |
113 | | assert_eq!(expected, encoded_varint64_len(n), "n={}", n); |
114 | | } |
115 | | |
116 | | for n in 0..1000 { |
117 | | test(n); |
118 | | } |
119 | | |
120 | | for p in 0.. { |
121 | | match 2u64.checked_pow(p) { |
122 | | Some(n) => test(n), |
123 | | None => break, |
124 | | } |
125 | | } |
126 | | |
127 | | for p in 0.. { |
128 | | match 3u64.checked_pow(p) { |
129 | | Some(n) => test(n), |
130 | | None => break, |
131 | | } |
132 | | } |
133 | | |
134 | | test(u64::MAX); |
135 | | test(u64::MAX - 1); |
136 | | test((i64::MAX as u64) + 1); |
137 | | test(i64::MAX as u64); |
138 | | test((i64::MAX as u64) - 1); |
139 | | test((u32::MAX as u64) + 1); |
140 | | test(u32::MAX as u64); |
141 | | test((u32::MAX as u64) - 1); |
142 | | test((i32::MAX as u64) + 1); |
143 | | test(i32::MAX as u64); |
144 | | test((i32::MAX as u64) - 1); |
145 | | } |
146 | | } |