1pub mod error;
8
9use bytes::{Buf, BufMut, Bytes, BytesMut};
10
11pub use self::error::{PrimitiveError, PrimitiveErrorKind};
12
13pub type Result<T> = core::result::Result<T, PrimitiveError>;
15
16const VARINT_MAX_BYTES: u8 = 5;
17const VARLONG_MAX_BYTES: u8 = 10;
18
19pub(crate) fn check_remaining(buf: &Bytes, needed: usize) -> Result<()> {
20 let available = buf.remaining();
21 if available < needed {
22 return Err(PrimitiveErrorKind::InsufficientData { needed, available }.into());
23 }
24 Ok(())
25}
26
27pub fn read_bool(buf: &mut Bytes) -> Result<bool> {
33 check_remaining(buf, 1)?;
34 Ok(buf.get_u8() != 0)
35}
36
37pub fn read_i8(buf: &mut Bytes) -> Result<i8> {
39 check_remaining(buf, 1)?;
40 Ok(buf.get_i8())
41}
42
43pub fn read_i16(buf: &mut Bytes) -> Result<i16> {
45 check_remaining(buf, 2)?;
46 Ok(buf.get_i16())
47}
48
49pub fn read_i32(buf: &mut Bytes) -> Result<i32> {
51 check_remaining(buf, 4)?;
52 Ok(buf.get_i32())
53}
54
55pub fn read_i64(buf: &mut Bytes) -> Result<i64> {
57 check_remaining(buf, 8)?;
58 Ok(buf.get_i64())
59}
60
61pub fn read_u16(buf: &mut Bytes) -> Result<u16> {
63 check_remaining(buf, 2)?;
64 Ok(buf.get_u16())
65}
66
67pub fn read_u32(buf: &mut Bytes) -> Result<u32> {
69 check_remaining(buf, 4)?;
70 Ok(buf.get_u32())
71}
72
73pub fn read_f64(buf: &mut Bytes) -> Result<f64> {
75 check_remaining(buf, 8)?;
76 Ok(buf.get_f64())
77}
78
79pub fn write_bool(buf: &mut BytesMut, value: bool) {
81 buf.put_u8(u8::from(value));
82}
83
84pub fn write_i8(buf: &mut BytesMut, value: i8) {
86 buf.put_i8(value);
87}
88
89pub fn write_i16(buf: &mut BytesMut, value: i16) {
91 buf.put_i16(value);
92}
93
94pub fn write_i32(buf: &mut BytesMut, value: i32) {
96 buf.put_i32(value);
97}
98
99pub fn write_i64(buf: &mut BytesMut, value: i64) {
101 buf.put_i64(value);
102}
103
104pub fn write_u16(buf: &mut BytesMut, value: u16) {
106 buf.put_u16(value);
107}
108
109pub fn write_u32(buf: &mut BytesMut, value: u32) {
111 buf.put_u32(value);
112}
113
114pub fn write_f64(buf: &mut BytesMut, value: f64) {
116 buf.put_f64(value);
117}
118
119pub fn read_unsigned_varint(buf: &mut Bytes) -> Result<u32> {
125 let mut value: u32 = 0;
126 for i in 0..VARINT_MAX_BYTES {
127 check_remaining(buf, 1)?;
128 let byte = buf.get_u8();
129 value |= u32::from(byte & 0x7f) << (u32::from(i) * 7);
130 if byte & 0x80 == 0 {
131 return Ok(value);
132 }
133 }
134 Err(PrimitiveErrorKind::InvalidVarint {
135 max_bytes: VARINT_MAX_BYTES,
136 }
137 .into())
138}
139
140pub fn write_unsigned_varint(buf: &mut BytesMut, mut value: u32) {
142 loop {
143 let low = value.to_le_bytes()[0] & 0x7f;
144 value >>= 7;
145 if value == 0 {
146 buf.put_u8(low);
147 return;
148 }
149 buf.put_u8(low | 0x80);
150 }
151}
152
153#[must_use]
155pub const fn unsigned_varint_len(value: u32) -> usize {
156 match value {
157 0x0..=0x7f => 1,
158 0x80..=0x3fff => 2,
159 0x4000..=0x1f_ffff => 3,
160 0x20_0000..=0xfff_ffff => 4,
161 0x1000_0000..=u32::MAX => 5,
162 }
163}
164
165#[must_use]
167pub const fn unsigned_varlong_len(value: u64) -> usize {
168 match value {
169 0x0..=0x7f => 1,
170 0x80..=0x3fff => 2,
171 0x4000..=0x1f_ffff => 3,
172 0x20_0000..=0xfff_ffff => 4,
173 0x1000_0000..=0x7_ffff_ffff => 5,
174 0x8_0000_0000..=0x3ff_ffff_ffff => 6,
175 0x400_0000_0000..=0x1_ffff_ffff_ffff => 7,
176 0x2_0000_0000_0000..=0xff_ffff_ffff_ffff => 8,
177 0x100_0000_0000_0000..=0x7fff_ffff_ffff_ffff => 9,
178 0x8000_0000_0000_0000..=u64::MAX => 10,
179 }
180}
181
182pub fn read_unsigned_varlong(buf: &mut Bytes) -> Result<u64> {
184 let mut value: u64 = 0;
185 for i in 0..VARLONG_MAX_BYTES {
186 check_remaining(buf, 1)?;
187 let byte = buf.get_u8();
188 value |= u64::from(byte & 0x7f) << (u32::from(i) * 7);
189 if byte & 0x80 == 0 {
190 return Ok(value);
191 }
192 }
193 Err(PrimitiveErrorKind::InvalidVarint {
194 max_bytes: VARLONG_MAX_BYTES,
195 }
196 .into())
197}
198
199pub fn write_unsigned_varlong(buf: &mut BytesMut, mut value: u64) {
201 loop {
202 let low = value.to_le_bytes()[0] & 0x7f;
203 value >>= 7;
204 if value == 0 {
205 buf.put_u8(low);
206 return;
207 }
208 buf.put_u8(low | 0x80);
209 }
210}
211
212pub fn read_signed_varint(buf: &mut Bytes) -> Result<i32> {
214 let v = read_unsigned_varint(buf)?;
215 let magnitude = (v >> 1).cast_signed();
216 let sign_mask = (v & 1).cast_signed().wrapping_neg();
217 Ok(magnitude ^ sign_mask)
218}
219
220pub fn write_signed_varint(buf: &mut BytesMut, value: i32) {
222 let encoded = ((value << 1) ^ (value >> 31)).cast_unsigned();
223 write_unsigned_varint(buf, encoded);
224}
225
226#[must_use]
228pub const fn signed_varint_len(value: i32) -> usize {
229 let encoded = ((value << 1) ^ (value >> 31)).cast_unsigned();
230 unsigned_varint_len(encoded)
231}
232
233pub fn read_signed_varlong(buf: &mut Bytes) -> Result<i64> {
235 let v = read_unsigned_varlong(buf)?;
236 let magnitude = (v >> 1).cast_signed();
237 let sign_mask = (v & 1).cast_signed().wrapping_neg();
238 Ok(magnitude ^ sign_mask)
239}
240
241pub fn write_signed_varlong(buf: &mut BytesMut, value: i64) {
243 let encoded = ((value << 1) ^ (value >> 63)).cast_unsigned();
244 write_unsigned_varlong(buf, encoded);
245}
246
247#[must_use]
249pub const fn signed_varlong_len(value: i64) -> usize {
250 let encoded = ((value << 1) ^ (value >> 63)).cast_unsigned();
251 unsigned_varlong_len(encoded)
252}
253
254pub fn read_array_length(buf: &mut Bytes) -> Result<i32> {
260 read_i32(buf)
261}
262
263pub fn write_array_length(buf: &mut BytesMut, len: i32) {
265 write_i32(buf, len);
266}
267
268#[must_use]
270pub const fn array_length_len() -> usize {
271 4
272}
273
274pub fn read_compact_array_length(buf: &mut Bytes) -> Result<i32> {
276 let raw = read_unsigned_varint(buf)?;
277 if raw == 0 {
278 Ok(-1)
279 } else {
280 let len = raw
281 .checked_sub(1)
282 .ok_or(PrimitiveErrorKind::InvalidVarint {
283 max_bytes: VARINT_MAX_BYTES,
284 })?;
285 i32::try_from(len).map_err(|_| PrimitiveErrorKind::LengthOutOfRange { length: len }.into())
286 }
287}
288
289pub fn write_compact_array_length(buf: &mut BytesMut, len: i32) {
291 if len < 0 {
292 write_unsigned_varint(buf, 0);
293 } else {
294 let encoded = len.cast_unsigned().saturating_add(1);
295 write_unsigned_varint(buf, encoded);
296 }
297}
298
299#[must_use]
301pub const fn compact_array_length_len(len: i32) -> usize {
302 if len < 0 {
303 unsigned_varint_len(0)
304 } else {
305 unsigned_varint_len(len.cast_unsigned().saturating_add(1))
306 }
307}
308
309#[must_use]
318pub fn array_read_capacity(len: i32, remaining: usize) -> usize {
319 const MAX_PREALLOC_ELEMENTS: usize = 1024;
321 usize::try_from(len)
322 .unwrap_or(0)
323 .min(remaining)
324 .min(MAX_PREALLOC_ELEMENTS)
325}
326
327#[cfg(test)]
328mod tests {
329 #![allow(
330 clippy::missing_assert_message,
331 reason = "Primitive helper tests keep assertions compact."
332 )]
333
334 use bytes::BytesMut;
335
336 use super::{
337 array_read_capacity, signed_varint_len, signed_varlong_len, write_signed_varint,
338 write_signed_varlong,
339 };
340
341 #[test]
342 fn array_read_capacity_never_trusts_the_claimed_length() {
343 assert_eq!(array_read_capacity(i32::MAX, 7), 7);
345 assert_eq!(array_read_capacity(-1, 100), 0);
347 assert_eq!(array_read_capacity(3, 100), 3);
349 assert_eq!(array_read_capacity(1_000_000, usize::MAX), 1024);
351 }
352
353 #[test]
354 fn signed_varint_len_matches_written_bytes() {
355 for value in [0, -1, 1, 63, 64, -64, i32::MAX, i32::MIN] {
356 let mut bytes = BytesMut::new();
357 write_signed_varint(&mut bytes, value);
358
359 assert_eq!(signed_varint_len(value), bytes.len());
360 }
361 }
362
363 #[test]
364 fn signed_varlong_len_matches_written_bytes() {
365 for value in [0, -1, 1, 63, 64, -64, i64::MAX, i64::MIN] {
366 let mut bytes = BytesMut::new();
367 write_signed_varlong(&mut bytes, value);
368
369 assert_eq!(signed_varlong_len(value), bytes.len());
370 }
371 }
372}