1use crate::{Decode, Encode, EncodedSize, Error, Result};
2
3const SEGMENT_BITS: u8 = 0x7F;
4const CONTINUE_BIT: u8 = 0x80;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub struct VarInt(pub i32);
17
18impl VarInt {
19 pub const MAX_BYTES: usize = 5;
21}
22
23impl Encode for VarInt {
30 fn encode(&self, buf: &mut Vec<u8>) -> Result<()> {
32 let mut value = self.0 as u32;
33 loop {
34 if value & !(SEGMENT_BITS as u32) == 0 {
35 buf.push(value as u8);
36 return Ok(());
37 }
38 buf.push((value as u8 & SEGMENT_BITS) | CONTINUE_BIT);
39 value >>= 7;
40 }
41 }
42}
43
44impl Decode for VarInt {
52 fn decode(buf: &mut &[u8]) -> Result<Self> {
54 let mut value: u32 = 0;
55 let mut position: u32 = 0;
56 let start = *buf;
57
58 loop {
59 if buf.is_empty() {
60 return Err(Error::BufferUnderflow {
61 needed: 1,
62 available: 0,
63 });
64 }
65
66 let byte = buf[0];
67 *buf = &buf[1..];
68
69 value |= ((byte & SEGMENT_BITS) as u32) << position;
70 position += 7;
71
72 if byte & CONTINUE_BIT == 0 {
73 return Ok(VarInt(value as i32));
74 }
75
76 if position >= 32 {
77 *buf = start;
79 return Err(Error::VarIntTooLarge);
80 }
81 }
82 }
83}
84
85impl EncodedSize for VarInt {
91 fn encoded_size(&self) -> usize {
92 let value = self.0 as u32;
93 match value {
94 0..=0x7F => 1,
95 0x80..=0x3FFF => 2,
96 0x4000..=0x1FFFFF => 3,
97 0x200000..=0xFFFFFFF => 4,
98 _ => 5,
99 }
100 }
101}
102
103impl From<i32> for VarInt {
105 fn from(value: i32) -> Self {
106 VarInt(value)
107 }
108}
109
110impl From<VarInt> for i32 {
112 fn from(value: VarInt) -> Self {
113 value.0
114 }
115}
116
117#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
124pub struct VarLong(pub i64);
125
126impl VarLong {
127 pub const MAX_BYTES: usize = 10;
129}
130
131impl Encode for VarLong {
137 fn encode(&self, buf: &mut Vec<u8>) -> Result<()> {
138 let mut value = self.0 as u64;
139 loop {
140 if value & !(SEGMENT_BITS as u64) == 0 {
141 buf.push(value as u8);
142 return Ok(());
143 }
144 buf.push((value as u8 & SEGMENT_BITS) | CONTINUE_BIT);
145 value >>= 7;
146 }
147 }
148}
149
150impl Decode for VarLong {
157 fn decode(buf: &mut &[u8]) -> Result<Self> {
158 let mut value: u64 = 0;
159 let mut position: u32 = 0;
160 let start = *buf;
161
162 loop {
163 if buf.is_empty() {
164 return Err(Error::BufferUnderflow {
165 needed: 1,
166 available: 0,
167 });
168 }
169
170 let byte = buf[0];
171 *buf = &buf[1..];
172
173 value |= ((byte & SEGMENT_BITS) as u64) << position;
174 position += 7;
175
176 if byte & CONTINUE_BIT == 0 {
177 return Ok(VarLong(value as i64));
178 }
179
180 if position >= 64 {
181 *buf = start;
182 return Err(Error::VarIntTooLarge);
183 }
184 }
185 }
186}
187
188impl EncodedSize for VarLong {
194 fn encoded_size(&self) -> usize {
195 let value = self.0 as u64;
196 match value {
197 0..=0x7F => 1,
198 0x80..=0x3FFF => 2,
199 0x4000..=0x1FFFFF => 3,
200 0x200000..=0xFFFFFFF => 4,
201 0x10000000..=0x7FFFFFFFF => 5,
202 0x800000000..=0x3FFFFFFFFFF => 6,
203 0x40000000000..=0x1FFFFFFFFFFFF => 7,
204 0x2000000000000..=0xFFFFFFFFFFFFFF => 8,
205 0x100000000000000..=0x7FFFFFFFFFFFFFFF => 9,
206 _ => 10,
207 }
208 }
209}
210
211impl From<i64> for VarLong {
213 fn from(value: i64) -> Self {
214 VarLong(value)
215 }
216}
217
218impl From<VarLong> for i64 {
220 fn from(value: VarLong) -> Self {
221 value.0
222 }
223}
224
225#[cfg(test)]
226mod tests {
227 use super::*;
228
229 fn roundtrip_varint(value: i32) {
230 let var = VarInt(value);
231 let mut buf = Vec::with_capacity(var.encoded_size());
232 var.encode(&mut buf).unwrap();
233 assert_eq!(buf.len(), var.encoded_size());
234
235 let mut cursor = buf.as_slice();
236 let decoded = VarInt::decode(&mut cursor).unwrap();
237 assert!(cursor.is_empty());
238 assert_eq!(decoded.0, value);
239 }
240
241 fn roundtrip_varlong(value: i64) {
242 let var = VarLong(value);
243 let mut buf = Vec::with_capacity(var.encoded_size());
244 var.encode(&mut buf).unwrap();
245 assert_eq!(buf.len(), var.encoded_size());
246
247 let mut cursor = buf.as_slice();
248 let decoded = VarLong::decode(&mut cursor).unwrap();
249 assert!(cursor.is_empty());
250 assert_eq!(decoded.0, value);
251 }
252
253 #[test]
256 fn varint_zero() {
257 let mut buf = Vec::new();
258 VarInt(0).encode(&mut buf).unwrap();
259 assert_eq!(buf, [0x00]);
260 roundtrip_varint(0);
261 }
262
263 #[test]
264 fn varint_one() {
265 let mut buf = Vec::new();
266 VarInt(1).encode(&mut buf).unwrap();
267 assert_eq!(buf, [0x01]);
268 roundtrip_varint(1);
269 }
270
271 #[test]
272 fn varint_127() {
273 let mut buf = Vec::new();
274 VarInt(127).encode(&mut buf).unwrap();
275 assert_eq!(buf, [0x7F]);
276 roundtrip_varint(127);
277 }
278
279 #[test]
280 fn varint_128() {
281 let mut buf = Vec::new();
282 VarInt(128).encode(&mut buf).unwrap();
283 assert_eq!(buf, [0x80, 0x01]);
284 roundtrip_varint(128);
285 }
286
287 #[test]
288 fn varint_255() {
289 let mut buf = Vec::new();
290 VarInt(255).encode(&mut buf).unwrap();
291 assert_eq!(buf, [0xFF, 0x01]);
292 roundtrip_varint(255);
293 }
294
295 #[test]
296 fn varint_25565() {
297 let mut buf = Vec::new();
298 VarInt(25565).encode(&mut buf).unwrap();
299 assert_eq!(buf, [0xDD, 0xC7, 0x01]);
300 roundtrip_varint(25565);
301 }
302
303 #[test]
304 fn varint_max() {
305 let mut buf = Vec::new();
306 VarInt(i32::MAX).encode(&mut buf).unwrap();
307 assert_eq!(buf, [0xFF, 0xFF, 0xFF, 0xFF, 0x07]);
308 roundtrip_varint(i32::MAX);
309 }
310
311 #[test]
312 fn varint_minus_one() {
313 let mut buf = Vec::new();
314 VarInt(-1).encode(&mut buf).unwrap();
315 assert_eq!(buf, [0xFF, 0xFF, 0xFF, 0xFF, 0x0F]);
316 roundtrip_varint(-1);
317 }
318
319 #[test]
320 fn varint_min() {
321 let mut buf = Vec::new();
322 VarInt(i32::MIN).encode(&mut buf).unwrap();
323 assert_eq!(buf, [0x80, 0x80, 0x80, 0x80, 0x08]);
324 roundtrip_varint(i32::MIN);
325 }
326
327 #[test]
330 fn varint_empty_buffer() {
331 let mut cursor: &[u8] = &[];
332 assert!(matches!(
333 VarInt::decode(&mut cursor),
334 Err(Error::BufferUnderflow { .. })
335 ));
336 }
337
338 #[test]
339 fn varint_too_large() {
340 let mut cursor: &[u8] = &[0x80, 0x80, 0x80, 0x80, 0x80, 0x01];
342 assert!(matches!(
343 VarInt::decode(&mut cursor),
344 Err(Error::VarIntTooLarge)
345 ));
346 }
347
348 #[test]
349 fn varint_truncated() {
350 let mut cursor: &[u8] = &[0x80];
352 assert!(matches!(
353 VarInt::decode(&mut cursor),
354 Err(Error::BufferUnderflow { .. })
355 ));
356 }
357
358 #[test]
361 fn varint_encoded_size() {
362 assert_eq!(VarInt(0).encoded_size(), 1);
363 assert_eq!(VarInt(127).encoded_size(), 1);
364 assert_eq!(VarInt(128).encoded_size(), 2);
365 assert_eq!(VarInt(16383).encoded_size(), 2);
366 assert_eq!(VarInt(16384).encoded_size(), 3);
367 assert_eq!(VarInt(i32::MAX).encoded_size(), 5);
368 assert_eq!(VarInt(-1).encoded_size(), 5);
369 assert_eq!(VarInt(i32::MIN).encoded_size(), 5);
370 }
371
372 #[test]
375 fn varint_from_i32() {
376 let v: VarInt = 42.into();
377 assert_eq!(v.0, 42);
378 }
379
380 #[test]
381 fn varint_into_i32() {
382 let v: i32 = VarInt(42).into();
383 assert_eq!(v, 42);
384 }
385
386 #[test]
389 fn varlong_zero() {
390 roundtrip_varlong(0);
391 }
392
393 #[test]
394 fn varlong_one() {
395 roundtrip_varlong(1);
396 }
397
398 #[test]
399 fn varlong_max() {
400 roundtrip_varlong(i64::MAX);
401 }
402
403 #[test]
404 fn varlong_min() {
405 roundtrip_varlong(i64::MIN);
406 }
407
408 #[test]
409 fn varlong_minus_one() {
410 roundtrip_varlong(-1);
411 }
412
413 #[test]
416 fn varlong_empty_buffer() {
417 let mut cursor: &[u8] = &[];
418 assert!(matches!(
419 VarLong::decode(&mut cursor),
420 Err(Error::BufferUnderflow { .. })
421 ));
422 }
423
424 #[test]
425 fn varlong_too_large() {
426 let mut cursor: &[u8] = &[0x80; 11];
428 assert!(matches!(
429 VarLong::decode(&mut cursor),
430 Err(Error::VarIntTooLarge)
431 ));
432 }
433
434 #[test]
437 fn varlong_encoded_size() {
438 assert_eq!(VarLong(0).encoded_size(), 1);
439 assert_eq!(VarLong(127).encoded_size(), 1);
440 assert_eq!(VarLong(128).encoded_size(), 2);
441 assert_eq!(VarLong(i64::MAX).encoded_size(), 9);
442 assert_eq!(VarLong(-1).encoded_size(), 10);
443 assert_eq!(VarLong(i64::MIN).encoded_size(), 10);
444 }
445
446 #[test]
449 fn varlong_from_i64() {
450 let v: VarLong = 42i64.into();
451 assert_eq!(v.0, 42);
452 }
453
454 #[test]
455 fn varlong_into_i64() {
456 let v: i64 = VarLong(42).into();
457 assert_eq!(v, 42);
458 }
459
460 mod proptests {
463 use super::*;
464 use proptest::prelude::*;
465
466 proptest! {
467 #[test]
468 fn varint_roundtrip(v: i32) {
469 roundtrip_varint(v);
470 }
471
472 #[test]
473 fn varlong_roundtrip(v: i64) {
474 roundtrip_varlong(v);
475 }
476 }
477 }
478}