protobuf_core/varint.rs
1// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Varint encoding and decoding logic for Protocol Buffers.
16//!
17//! This module provides basic varint operations including encoding, decoding,
18//! and conversion to various protobuf integer types.
19//!
20//! This is a **reference implementation**. Not optimized for performance.
21
22use crate::wire_format::{MAX_VARINT_BYTES, VARINT_CONTINUATION_BIT, VARINT_PAYLOAD_MASK};
23use crate::{ProtobufError, Result};
24use ::std::convert::{Infallible, TryFrom};
25use ::std::io::{Read, Write};
26use ::std::iter::Iterator;
27
28/// A deserialized varint value.
29///
30/// This type represents the decoded 8-byte value from serialized bytes
31/// to protobuf integer types.
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33pub struct Varint([u8; 8]);
34
35impl Varint {
36 // ============================================================================
37 // Converting from / to [u8; 8]
38 // ============================================================================
39
40 /// Create a new Varint from raw bytes.
41 ///
42 /// The bytes given are, essentially, a little-endian encoded u64.
43 /// Note that this is NOT the "protobuf encoded" varint bytes.
44 pub fn new(bytes: [u8; 8]) -> Self {
45 Self(bytes)
46 }
47
48 /// Get the underlying byte array, the little-endian encoded u64.
49 /// Note that this is NOT the "protobuf encoded" varint bytes.
50 pub fn as_bytes(&self) -> &[u8; 8] {
51 &self.0
52 }
53
54 // ============================================================================
55 // from / to rust integer types, using certain protobuf integer types formats.
56 // ============================================================================
57
58 /// Create a Varint from `u64`, assuming `UInt64` protobuf type.
59 pub fn from_uint64(value: u64) -> Self {
60 let bytes = value.to_le_bytes();
61 Self(bytes)
62 }
63
64 /// Create a Varint from `u32`, assuming `UInt32` protobuf type.
65 pub fn from_uint32(value: u32) -> Self {
66 let bytes = (value as u64).to_le_bytes();
67 Self(bytes)
68 }
69
70 /// Create a Varint from `i64`, assuming `SInt64` protobuf type.
71 pub fn from_sint64(value: i64) -> Self {
72 let zigzag_value = if value < 0 {
73 ((-value) as u64) * 2 - 1
74 } else {
75 (value as u64) * 2
76 };
77 let bytes = zigzag_value.to_le_bytes();
78 Self(bytes)
79 }
80
81 /// Create a Varint from `i32`, assuming `SInt32` protobuf type.
82 pub fn from_sint32(value: i32) -> Self {
83 Self::from_sint64(value as i64)
84 }
85
86 /// Create a Varint from `i64`, assuming `Int64` protobuf type.
87 pub fn from_int64(value: i64) -> Self {
88 let bytes = (value as u64).to_le_bytes();
89 Self(bytes)
90 }
91
92 /// Create a Varint from `i32`, assuming `Int32` protobuf type.
93 pub fn from_int32(value: i32) -> Self {
94 let bytes = (value as u64).to_le_bytes();
95 Self(bytes)
96 }
97
98 /// Create a Varint from `bool`, assuming `Bool` protobuf type.
99 pub fn from_bool(value: bool) -> Self {
100 let bytes = (if value { 1u64 } else { 0u64 }).to_le_bytes();
101 Self(bytes)
102 }
103
104 /// Convert to `u64`, assuming `UInt64` protobuf type.
105 pub fn to_uint64(&self) -> u64 {
106 u64::from_le_bytes(self.0)
107 }
108
109 /// Convert to `u32`, assuming `UInt32` protobuf type.
110 /// Returns an error if the value is out of range for `u32`.
111 pub fn try_to_uint32(&self) -> Result<u32> {
112 let value = self.to_uint64();
113 u32::try_from(value).map_err(|_| ProtobufError::VarintDowncastOutOfRange {
114 value,
115 target_type: "u32",
116 })
117 }
118
119 /// Convert to `i64`, assuming `SInt64` protobuf type.
120 pub fn to_sint64(&self) -> i64 {
121 let value = self.to_uint64();
122 ((value >> 1) as i64) ^ (-((value & 1) as i64))
123 }
124
125 /// Convert to `i32`, assuming `SInt32` protobuf type.
126 /// Returns an error if the value is out of range for `i32`.
127 pub fn try_to_sint32(&self) -> Result<i32> {
128 let sint64_value = self.to_sint64();
129 i32::try_from(sint64_value).map_err(|_| ProtobufError::VarintDowncastOutOfRange {
130 value: sint64_value as u64,
131 target_type: "i32",
132 })
133 }
134
135 /// Convert to `i64`, assuming `Int64` protobuf type.
136 pub fn to_int64(&self) -> i64 {
137 i64::from_le_bytes(self.0)
138 }
139
140 /// Convert to `i32`, assuming `Int32` protobuf type.
141 /// Returns an error if the value is out of range for `i32`.
142 pub fn try_to_int32(&self) -> Result<i32> {
143 let value = self.to_int64();
144 i32::try_from(value).map_err(|_| ProtobufError::VarintDowncastOutOfRange {
145 value: value as u64,
146 target_type: "i32",
147 })
148 }
149
150 /// Convert to `bool`, assuming `Bool` protobuf type.
151 pub fn to_bool(&self) -> bool {
152 self.to_uint64() != 0
153 }
154
155 // ============================================================================
156 // serialization
157 // ============================================================================
158
159 /// Get the size of this varint when encoded as a varint.
160 ///
161 /// This method calculates the exact number of bytes needed to encode
162 /// the underlying value as a protobuf varint.
163 pub fn varint_size(&self) -> usize {
164 let value = self.to_uint64();
165 if value == 0 {
166 1
167 } else {
168 (64 - value.leading_zeros() as usize).div_ceil(7)
169 }
170 }
171
172 /// Encode this varint as a varint and return the bytes with count.
173 ///
174 /// Returns a tuple of (bytes, count) where:
175 /// - bytes: fixed-size array containing the encoded varint
176 /// - count: actual number of bytes used (1-MAX_VARINT_BYTES)
177 ///
178 /// # Example
179 /// ```
180 /// use ::protobuf_core::Varint;
181 ///
182 /// let varint = Varint::from_uint64(150);
183 /// let (bytes, count) = varint.encode();
184 /// assert_eq!(count, 2);
185 /// assert_eq!(&bytes[..count], &[0x96, 0x01]);
186 /// ```
187 pub fn encode(&self) -> ([u8; MAX_VARINT_BYTES], usize) {
188 let value = self.to_uint64();
189 let mut bytes = [0u8; MAX_VARINT_BYTES];
190 let mut bytes_written = 0;
191 let mut remaining_value = value;
192
193 for byte in bytes.iter_mut() {
194 *byte = (remaining_value & VARINT_PAYLOAD_MASK as u64) as u8;
195 remaining_value >>= 7;
196 bytes_written += 1;
197
198 if remaining_value == 0 {
199 break;
200 } else {
201 *byte |= VARINT_CONTINUATION_BIT; // continuation bit
202 }
203 }
204
205 (bytes, bytes_written)
206 }
207}
208
209/// Iterator that reads multiple varints from a byte iterator.
210///
211/// This iterator yields `Result<Varint>` for each varint read from the underlying iterator.
212/// It stops when there are no more bytes available or an error occurs.
213pub struct VarintIterator<I: Iterator> {
214 bytes: I,
215}
216
217/// Iterator adapter that converts `Iterator<Item = u8>` to `Iterator<Item = Result<u8, Infallible>>`.
218///
219/// This wraps each `u8` value from the inner iterator with `Ok()`.
220pub struct ToResultIterator<I> {
221 inner: I,
222}
223
224impl<I> Iterator for ToResultIterator<I>
225where
226 I: Iterator<Item = u8>,
227{
228 type Item = ::std::result::Result<u8, Infallible>;
229
230 fn next(&mut self) -> Option<Self::Item> {
231 self.inner.next().map(Ok)
232 }
233}
234
235impl<I, E> VarintIterator<I>
236where
237 I: Iterator<Item = ::std::result::Result<u8, E>>,
238 E: Into<ProtobufError>,
239{
240 fn new(bytes: I) -> Self {
241 Self { bytes }
242 }
243}
244
245impl<I, E> Iterator for VarintIterator<I>
246where
247 I: Iterator<Item = ::std::result::Result<u8, E>>,
248 E: Into<ProtobufError>,
249{
250 type Item = Result<Varint>;
251
252 fn next(&mut self) -> Option<Self::Item> {
253 decode_varint_from_bytes(&mut self.bytes).transpose()
254 }
255}
256
257/// Decode a varint from a sequence of bytes.
258///
259/// This is a helper function that implements the core varint decoding logic.
260/// It reads bytes from the iterator until it finds a byte with the continuation bit cleared.
261///
262/// Returns `Ok(Some(Varint))` if successfully decoded.
263/// Returns `Ok(None)` if no bytes were read (empty iterator).
264/// Returns `Err(ProtobufError::VarintTooLong)` if the varint exceeds MAX_VARINT_BYTES.
265/// Returns `Err(ProtobufError)` if an error occurs while reading bytes (the error type `E` is converted via `Into<ProtobufError>`).
266fn decode_varint_from_bytes<I, E>(bytes: I) -> Result<Option<Varint>>
267where
268 I: Iterator<Item = ::std::result::Result<u8, E>>,
269 E: Into<ProtobufError>,
270{
271 let mut decoded_value = 0u64;
272 let mut shift = 0;
273 let mut has_data = false;
274
275 for byte_result in bytes.take(MAX_VARINT_BYTES) {
276 let byte = byte_result.map_err(Into::into)?;
277 has_data = true;
278
279 let value = (byte & VARINT_PAYLOAD_MASK) as u64;
280 decoded_value |= value << shift;
281
282 if byte & VARINT_CONTINUATION_BIT == 0 {
283 let result_bytes = decoded_value.to_le_bytes();
284 return Ok(Some(Varint::new(result_bytes)));
285 }
286 shift += 7;
287 }
288
289 if !has_data {
290 return Ok(None);
291 }
292
293 Err(ProtobufError::VarintTooLong)
294}
295
296/// Extension trait for collecting varints from byte iterators.
297///
298/// This trait provides convenient methods to collect varints directly from
299/// any iterator that yields bytes.
300///
301/// # Example
302/// ```
303/// use ::protobuf_core::{IteratorExtVarint, Varint};
304///
305/// let bytes = vec![0x96, 0x01]; // 150 in varint encoding
306/// let mut iter = bytes.into_iter();
307/// let varint: Option<Varint> = iter.read_varint().unwrap();
308/// assert_eq!(varint.unwrap().to_uint64(), 150);
309/// ```
310pub trait IteratorExtVarint {
311 /// Read a varint from this iterator.
312 ///
313 /// Returns the Varint `Ok(Some(varint))` if successfully read.
314 /// Returns `Ok(None)` if no input is available (empty iterator).
315 /// Returns `Err(ProtobufError::VarintTooLong)` if the varint exceeds MAX_VARINT_BYTES.
316 fn read_varint(self) -> Result<Option<Varint>>;
317
318 /// Create an iterator that reads multiple varints from this iterator.
319 ///
320 /// Returns an iterator that yields `Result<Varint>` for each varint read.
321 /// The iterator stops when there are no more bytes available or an error occurs.
322 ///
323 /// # Example
324 /// ```
325 /// use ::protobuf_core::{IteratorExtVarint, Varint};
326 ///
327 /// let bytes = vec![0x96, 0x01, 0x7F]; // 150 and 127 in varint encoding
328 /// let iter = bytes.into_iter();
329 /// let varints: Vec<Varint> = iter.read_varints().collect::<Result<Vec<_>, _>>().unwrap();
330 /// assert_eq!(varints.len(), 2);
331 /// assert_eq!(varints[0].to_uint64(), 150);
332 /// assert_eq!(varints[1].to_uint64(), 127);
333 /// ```
334 fn read_varints(self) -> VarintIterator<ToResultIterator<Self>>
335 where
336 Self: Sized + Iterator<Item = u8>;
337}
338
339impl<I> IteratorExtVarint for I
340where
341 I: Iterator<Item = u8>,
342{
343 fn read_varint(self) -> Result<Option<Varint>> {
344 decode_varint_from_bytes(self.map(Ok::<u8, Infallible>))
345 }
346
347 fn read_varints(self) -> VarintIterator<ToResultIterator<Self>>
348 where
349 Self: Sized,
350 {
351 VarintIterator::new(ToResultIterator { inner: self })
352 }
353}
354
355/// Extension trait for reading varints from byte iterators that yield `Result<u8, E>`.
356///
357/// This trait provides convenient methods to read varints directly from
358/// any iterator that yields `Result<u8, E>`, allowing proper error propagation.
359/// The error type `E` must implement `Into<ProtobufError>`.
360///
361/// # Example
362/// ```
363/// use ::std::io::{Cursor, Read};
364/// use ::protobuf_core::{TryIteratorExtVarint, Varint};
365///
366/// let data = vec![0x96, 0x01]; // 150 in varint encoding
367/// let mut reader = Cursor::new(data);
368/// let iter = reader.bytes(); // Iterator<Item = Result<u8, io::Error>>
369/// let varint = iter.read_varint().unwrap().unwrap();
370/// assert_eq!(varint.to_uint64(), 150);
371/// ```
372pub trait TryIteratorExtVarint {
373 /// Read a varint from this iterator.
374 ///
375 /// Returns the Varint `Ok(Some(varint))` if successfully read.
376 /// Returns `Ok(None)` if no input is available (empty iterator).
377 /// Returns `Err(ProtobufError::VarintTooLong)` if the varint exceeds MAX_VARINT_BYTES.
378 /// Returns `Err(ProtobufError)` if an error occurs while reading bytes (the error type `E` is converted via `Into<ProtobufError>`).
379 fn read_varint(self) -> Result<Option<Varint>>;
380
381 /// Create an iterator that reads multiple varints from this iterator.
382 ///
383 /// Returns an iterator that yields `Result<Varint>` for each varint read.
384 /// The iterator stops when there are no more bytes available or an error occurs.
385 ///
386 /// # Example
387 /// ```
388 /// use ::std::io::{Cursor, Read};
389 /// use ::protobuf_core::{TryIteratorExtVarint, Varint};
390 ///
391 /// let data = vec![0x96, 0x01, 0x7F]; // 150 and 127 in varint encoding
392 /// let reader = Cursor::new(data);
393 /// let iter = reader.bytes();
394 /// let varints: Vec<Varint> = iter.read_varints().collect::<Result<Vec<_>, _>>().unwrap();
395 /// assert_eq!(varints.len(), 2);
396 /// assert_eq!(varints[0].to_uint64(), 150);
397 /// assert_eq!(varints[1].to_uint64(), 127);
398 /// ```
399 fn read_varints(self) -> VarintIterator<Self>
400 where
401 Self: Sized + Iterator;
402}
403
404impl<I, E> TryIteratorExtVarint for I
405where
406 I: Iterator<Item = ::std::result::Result<u8, E>>,
407 E: Into<ProtobufError>,
408{
409 fn read_varint(self) -> Result<Option<Varint>> {
410 decode_varint_from_bytes(self)
411 }
412
413 fn read_varints(self) -> VarintIterator<Self>
414 where
415 Self: Sized,
416 {
417 VarintIterator::new(self)
418 }
419}
420
421/// Extension trait for reading varints from Read instances.
422///
423/// This trait provides a convenient method to read varints directly from
424/// any type that implements `std::io::Read`.
425///
426/// # Performance Note
427///
428/// When reading from file handles or network streams, consider wrapping the reader
429/// with [`BufReader`](std::io::BufReader) to avoid inefficient byte-by-byte system calls:
430///
431/// ```no_run
432/// use std::io::{BufReader, Read};
433/// use protobuf_core::ReadExtVarint;
434///
435/// # fn example() -> Result<(), Box<dyn std::error::Error>> {
436/// let file = std::fs::File::open("data.bin")?;
437/// let mut reader = BufReader::new(file);
438/// let varint = reader.read_varint()?;
439/// # Ok(())
440/// # }
441/// ```
442///
443/// # Example
444/// ```
445/// use ::std::io::Cursor;
446/// use ::protobuf_core::{ReadExtVarint, Varint};
447///
448/// let data = vec![0x96, 0x01]; // 150 in varint encoding
449/// let mut reader = Cursor::new(data);
450/// let varint = reader.read_varint().unwrap().unwrap();
451/// assert_eq!(varint.to_uint64(), 150);
452/// ```
453pub trait ReadExtVarint {
454 /// Read a varint from this reader.
455 ///
456 /// Returns the Varint `Ok(Some(varint))` if successfully read.
457 /// Returns `Ok(None)` if no input is available (EOF).
458 /// Returns `Err(ProtobufError::VarintTooLong)` if the varint exceeds MAX_VARINT_BYTES.
459 /// Returns `Err(ProtobufError::IoError)` if an I/O error occurs.
460 fn read_varint(&mut self) -> Result<Option<Varint>>;
461
462 /// Create an iterator that reads multiple varints from this reader.
463 ///
464 /// Returns an iterator that yields `Result<Varint>` for each varint read.
465 /// The iterator stops when there are no more bytes available (EOF) or an error occurs.
466 ///
467 /// # Example
468 /// ```
469 /// use ::std::io::Cursor;
470 /// use ::protobuf_core::{ReadExtVarint, Varint};
471 ///
472 /// let data = vec![0x96, 0x01, 0x7F]; // 150 and 127 in varint encoding
473 /// let mut reader = Cursor::new(data);
474 /// let varints: Vec<Varint> = reader.read_varints().collect::<Result<Vec<_>, _>>().unwrap();
475 /// assert_eq!(varints.len(), 2);
476 /// assert_eq!(varints[0].to_uint64(), 150);
477 /// assert_eq!(varints[1].to_uint64(), 127);
478 /// ```
479 fn read_varints(&mut self) -> VarintIterator<::std::io::Bytes<&mut Self>>
480 where
481 Self: ::std::io::Read;
482}
483
484impl<R> ReadExtVarint for R
485where
486 R: Read,
487{
488 #[allow(clippy::unbuffered_bytes)] // Varint parsing requires byte-by-byte reading; caller should use BufReader for efficiency
489 fn read_varint(&mut self) -> Result<Option<Varint>> {
490 decode_varint_from_bytes(self.bytes())
491 }
492
493 #[allow(clippy::unbuffered_bytes)] // Varint parsing requires byte-by-byte reading; caller should use BufReader for efficiency
494 fn read_varints(&mut self) -> VarintIterator<::std::io::Bytes<&mut Self>> {
495 VarintIterator::new(self.bytes())
496 }
497}
498
499/// Extension trait for writing varints to Write instances.
500///
501/// This trait provides a convenient method to write varints directly to
502/// any type that implements `std::io::Write`.
503///
504/// # Example
505/// ```
506/// use ::std::io::Write;
507/// use ::protobuf_core::{WriteExtVarint, Varint};
508///
509/// let varint = Varint::from_uint64(150);
510/// let mut writer = Vec::new();
511/// writer.write_varint(&varint).unwrap();
512/// assert_eq!(writer, vec![0x96, 0x01]);
513/// ```
514pub trait WriteExtVarint {
515 /// Write a varint to this writer.
516 ///
517 /// Encodes a Varint as a varint and writes it to this writer.
518 /// Returns the number of bytes written on success.
519 ///
520 /// # Arguments
521 /// * `value` - The Varint to encode and write
522 ///
523 /// # Returns
524 /// * `Ok(usize)` - Number of bytes written
525 /// * `Err(::std::io::Error)` - I/O error from the writer
526 ///
527 /// # Example
528 /// ```
529 /// use ::std::io::Write;
530 /// use ::protobuf_core::{WriteExtVarint, Varint};
531 ///
532 /// let varint = Varint::from_uint64(150);
533 /// let mut buffer = Vec::new();
534 /// let bytes_written = buffer.write_varint(&varint).unwrap();
535 /// assert_eq!(bytes_written, 2);
536 /// assert_eq!(buffer, vec![0x96, 0x01]);
537 /// ```
538 fn write_varint(&mut self, value: &Varint) -> ::std::io::Result<usize>;
539}
540
541impl<W> WriteExtVarint for W
542where
543 W: Write,
544{
545 fn write_varint(&mut self, value: &Varint) -> ::std::io::Result<usize> {
546 let (bytes, count) = value.encode();
547 self.write_all(&bytes[..count])?;
548 Ok(count)
549 }
550}
551
552#[cfg(test)]
553mod tests {
554 use super::{MAX_VARINT_BYTES, Result, Varint};
555
556 // ============================================================================
557 // Basic Varint tests (no traits)
558 // ============================================================================
559
560 #[test]
561 fn test_varint_value_creation() {
562 let bytes = [0x96, 0x01, 0, 0, 0, 0, 0, 0];
563 let varint = Varint::new(bytes);
564 assert_eq!(varint.as_bytes(), &bytes);
565 }
566
567 #[test]
568 fn test_varint_conversions() {
569 // 406 in little-endian: 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
570 let bytes = [0x96, 0x01, 0, 0, 0, 0, 0, 0];
571 let varint = Varint::new(bytes);
572
573 // Test all integer conversions
574 assert_eq!(varint.to_uint64(), 406);
575 match varint.try_to_uint32() {
576 Ok(value) => assert_eq!(value, 406),
577 Err(e) => panic!("Expected Ok(406), got error: {:?}", e),
578 }
579
580 let varint = Varint::new(bytes);
581 // 406 in ZigZag encoding represents 203 in signed value
582 assert_eq!(varint.to_sint64(), 203);
583
584 let varint = Varint::new(bytes);
585 match varint.try_to_sint32() {
586 Ok(value) => assert_eq!(value, 203),
587 Err(e) => panic!("Expected Ok(203), got error: {:?}", e),
588 }
589
590 let varint = Varint::new(bytes);
591 assert_eq!(varint.to_bool(), true);
592 }
593
594 #[test]
595 fn test_signed_integer_conversions() {
596 // -1 in ZigZag encoding: 1
597 let bytes = [0x01, 0, 0, 0, 0, 0, 0, 0];
598 let varint = Varint::new(bytes);
599
600 assert_eq!(varint.to_sint64(), -1);
601
602 let varint = Varint::new(bytes);
603 match varint.try_to_sint32() {
604 Ok(value) => assert_eq!(value, -1),
605 Err(e) => panic!("Expected Ok(-1), got error: {:?}", e),
606 }
607 }
608
609 #[test]
610 fn test_from_traits() {
611 // Test From<u64> for Varint
612 let varint = Varint::from_uint64(150);
613 assert_eq!(varint.to_uint64(), 150);
614
615 // Test from_uint32
616 let varint = Varint::from_uint32(150);
617 assert_eq!(varint.to_uint64(), 150);
618
619 // Test from_sint64
620 let varint = Varint::from_sint64(150);
621 assert_eq!(varint.to_sint64(), 150);
622
623 // Test from_sint64 with negative value
624 let varint = Varint::from_sint64(-1);
625 assert_eq!(varint.to_sint64(), -1);
626
627 // Test from_bool
628 let varint = Varint::from_bool(true);
629 assert_eq!(varint.to_bool(), true);
630
631 // Test from_int32 (non-ZigZag)
632 let varint = Varint::from_int32(150);
633 assert_eq!(varint.to_int64(), 150);
634
635 // Test from_int64 (non-ZigZag)
636 let varint = Varint::from_int64(150);
637 assert_eq!(varint.to_int64(), 150);
638 }
639
640 #[test]
641 fn test_to_methods() {
642 let bytes = [150, 0, 0, 0, 0, 0, 0, 0]; // 150 in little-endian
643 let varint = Varint::new(bytes);
644
645 // Test to_uint32
646 assert_eq!(varint.try_to_uint32().unwrap(), 150);
647
648 // Test to_sint32 (150 in ZigZag encoding represents 75 in signed value)
649 assert_eq!(varint.try_to_sint32().unwrap(), 75);
650
651 // Test to_sint64 (150 in ZigZag encoding represents 75 in signed value)
652 assert_eq!(varint.to_sint64(), 75);
653
654 // Test to_bool
655 assert_eq!(varint.to_bool(), true);
656
657 // Test to_int32 (non-ZigZag)
658 assert_eq!(varint.try_to_int32().unwrap(), 150);
659
660 // Test to_int64 (non-ZigZag)
661 assert_eq!(varint.to_int64(), 150);
662 }
663
664 #[test]
665 fn test_roundtrip_conversions() {
666 // Test roundtrip for u64
667 let original = 150u64;
668 let varint = Varint::from_uint64(original);
669 assert_eq!(varint.to_uint64(), original);
670
671 // Test roundtrip for u32
672 let original = 150u32;
673 let varint = Varint::from_uint32(original);
674 let converted = varint.try_to_uint32().unwrap();
675 assert_eq!(converted, original);
676
677 // Test roundtrip for i64 (ZigZag)
678 let original = -1i64;
679 let varint = Varint::from_sint64(original);
680 let converted = varint.to_sint64();
681 assert_eq!(converted, original);
682
683 // Test roundtrip for i64 (non-ZigZag)
684 let original = 150i64;
685 let varint = Varint::from_int64(original);
686 let converted = varint.to_int64();
687 assert_eq!(converted, original);
688
689 // Test roundtrip for i32 (non-ZigZag)
690 let original = 150i32;
691 let varint = Varint::from_int32(original);
692 let converted = varint.try_to_int32().unwrap();
693 assert_eq!(converted, original);
694
695 // Test roundtrip for bool
696 let original = true;
697 let varint = Varint::from_bool(original);
698 let converted = varint.to_bool();
699 assert_eq!(converted, original);
700 }
701
702 // ============================================================================
703 // Encoding tests
704 // ============================================================================
705
706 #[test]
707 fn test_encode_varint() {
708 // Test encoding small values
709 let varint = Varint::from_uint64(150);
710 let (bytes, count) = varint.encode();
711 assert_eq!(count, 2);
712 assert_eq!(&bytes[..count], &[0x96, 0x01]);
713
714 // Test encoding single-byte values
715 let varint = Varint::from_uint64(127);
716 let (bytes, count) = varint.encode();
717 assert_eq!(count, 1);
718 assert_eq!(&bytes[..count], &[0x7F]);
719
720 // Test encoding zero
721 let varint = Varint::from_uint64(0);
722 let (bytes, count) = varint.encode();
723 assert_eq!(count, 1);
724 assert_eq!(&bytes[..count], &[0x00]);
725
726 // Test encoding large values
727 let varint = Varint::from_uint64(0x7FFFFFFFFFFFFFFF);
728 let (bytes, count) = varint.encode();
729 assert_eq!(count, 9);
730 assert_eq!(
731 &bytes[..count],
732 &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F]
733 );
734
735 // Test encoding maximum varint (MAX_VARINT_BYTES bytes)
736 let varint = Varint::from_uint64(0xFFFFFFFFFFFFFFFF);
737 let (bytes, count) = varint.encode();
738 assert_eq!(count, MAX_VARINT_BYTES);
739 assert_eq!(
740 &bytes[..count],
741 &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01]
742 );
743 }
744
745 #[test]
746 fn test_write_varint() {
747 use super::WriteExtVarint;
748
749 // Test encoding small values
750 let varint = Varint::from_uint64(150);
751 let mut buffer = Vec::new();
752 let bytes_written = buffer.write_varint(&varint).unwrap();
753 assert_eq!(bytes_written, 2);
754 assert_eq!(buffer, vec![0x96, 0x01]);
755
756 // Test encoding single-byte values
757 let varint = Varint::from_uint64(127);
758 let mut buffer = Vec::new();
759 let bytes_written = buffer.write_varint(&varint).unwrap();
760 assert_eq!(bytes_written, 1);
761 assert_eq!(buffer, vec![0x7F]);
762
763 // Test encoding zero
764 let varint = Varint::from_uint64(0);
765 let mut buffer = Vec::new();
766 let bytes_written = buffer.write_varint(&varint).unwrap();
767 assert_eq!(bytes_written, 1);
768 assert_eq!(buffer, vec![0x00]);
769
770 // Test encoding large values
771 let varint = Varint::from_uint64(0x7FFFFFFFFFFFFFFF);
772 let mut buffer = Vec::new();
773 let bytes_written = buffer.write_varint(&varint).unwrap();
774 assert_eq!(bytes_written, 9); // 9-byte varint
775
776 // Test encoding maximum varint (MAX_VARINT_BYTES bytes)
777 let varint = Varint::from_uint64(0xFFFFFFFFFFFFFFFF);
778 let mut buffer = Vec::new();
779 let bytes_written = buffer.write_varint(&varint).unwrap();
780 assert_eq!(bytes_written, MAX_VARINT_BYTES); // Maximum varint size
781 }
782
783 #[test]
784 fn test_all_encoding_methods_consistency() {
785 use super::WriteExtVarint;
786
787 let test_values = vec![0, 1, 127, 128, 150, 255, 256, 65535, 0x7FFFFFFF];
788
789 for &value in &test_values {
790 // Method 1: encode method
791 let varint = Varint::from_uint64(value);
792 let (array_bytes, array_count) = varint.encode();
793
794 // Method 2: write_varint (std::io::Write)
795 let varint2 = Varint::from_uint64(value);
796 let mut vec_buffer = Vec::new();
797 let vec_count = vec_buffer.write_varint(&varint2).unwrap();
798
799 // Both methods should produce the same result
800 assert_eq!(array_count, vec_count);
801 assert_eq!(&array_bytes[..array_count], &vec_buffer[..]);
802 }
803 }
804
805 // ============================================================================
806 // IteratorExtVarint tests
807 // ============================================================================
808
809 #[test]
810 fn test_read_varint_from_iterator() {
811 use super::IteratorExtVarint;
812
813 let input = [0x96, 0x01];
814 let iter = input.iter().copied();
815 let varint = iter.read_varint().unwrap().unwrap();
816
817 assert_eq!(varint.to_uint64(), 150);
818 }
819
820 #[test]
821 fn test_iterator_ext_varint_trait() {
822 use super::IteratorExtVarint;
823
824 let bytes = vec![0x96, 0x01]; // 150 in varint encoding
825 let iter = bytes.into_iter();
826 let varint = iter.read_varint().unwrap().unwrap();
827
828 assert_eq!(varint.to_uint64(), 150);
829 }
830
831 #[test]
832 fn test_iterator_ext_varint_empty() {
833 use super::IteratorExtVarint;
834
835 let varint = IteratorExtVarint::read_varint(::std::iter::empty()).unwrap();
836
837 assert_eq!(varint, None);
838 }
839
840 #[test]
841 fn test_iterator_ext_varint_read_varints() {
842 use super::IteratorExtVarint;
843
844 let bytes = vec![0x96, 0x01, 0x7F, 0x01]; // 150, 127, 1 in varint encoding
845 let iter = bytes.into_iter();
846 let varints: Vec<Varint> = iter.read_varints().collect::<Result<Vec<_>>>().unwrap();
847 assert_eq!(varints.len(), 3);
848 assert_eq!(varints[0].to_uint64(), 150);
849 assert_eq!(varints[1].to_uint64(), 127);
850 assert_eq!(varints[2].to_uint64(), 1);
851 }
852
853 // ============================================================================
854 // TryIteratorExtVarint tests
855 // ============================================================================
856
857 #[test]
858 fn test_try_iterator_ext_varint() {
859 use super::TryIteratorExtVarint;
860 use ::std::io::{Cursor, Read};
861
862 let data = vec![0x96, 0x01]; // 150 in varint encoding
863 let reader = Cursor::new(data);
864 let iter = reader.bytes();
865 let varint = TryIteratorExtVarint::read_varint(iter).unwrap().unwrap();
866 assert_eq!(varint.to_uint64(), 150);
867 }
868
869 #[test]
870 fn test_try_iterator_ext_varint_empty() {
871 use super::TryIteratorExtVarint;
872 use ::std::io::{Cursor, Read};
873
874 let data = vec![];
875 let reader = Cursor::new(data);
876 let iter = reader.bytes();
877 let varint = TryIteratorExtVarint::read_varint(iter).unwrap();
878 assert_eq!(varint, None);
879 }
880
881 #[test]
882 fn test_try_iterator_ext_varint_error() {
883 use super::TryIteratorExtVarint;
884 use crate::ProtobufError;
885 use ::std::io::ErrorKind;
886
887 // Create an iterator that returns an error
888 let error = ::std::io::Error::new(ErrorKind::UnexpectedEof, "test error");
889 let iter = ::std::iter::once(Err(error));
890 let result = TryIteratorExtVarint::read_varint(iter);
891
892 assert!(result.is_err());
893 if let Err(ProtobufError::IoError(io_err)) = result {
894 assert_eq!(io_err.kind(), ErrorKind::UnexpectedEof);
895 } else {
896 panic!("Expected IoError");
897 }
898 }
899
900 #[test]
901 fn test_try_iterator_ext_varint_read_varints() {
902 use super::TryIteratorExtVarint;
903 use ::std::io::{Cursor, Read};
904
905 let data = vec![0x96, 0x01, 0x7F, 0x01]; // 150, 127, 1 in varint encoding
906 let reader = Cursor::new(data);
907 let iter = reader.bytes();
908 let varints: Vec<Varint> = iter.read_varints().collect::<Result<Vec<_>>>().unwrap();
909 assert_eq!(varints.len(), 3);
910 assert_eq!(varints[0].to_uint64(), 150);
911 assert_eq!(varints[1].to_uint64(), 127);
912 assert_eq!(varints[2].to_uint64(), 1);
913 }
914
915 // ============================================================================
916 // ReadExtVarint tests
917 // ============================================================================
918
919 #[test]
920 fn test_read_ext_varint_trait() {
921 use super::ReadExtVarint;
922 use ::std::io::Cursor;
923
924 let input = [0x96, 0x01];
925 let mut reader = Cursor::new(input);
926 let varint = reader.read_varint().unwrap().unwrap();
927
928 assert_eq!(varint.to_uint64(), 150);
929 }
930
931 #[test]
932 fn test_read_ext_varint_read_varints() {
933 use super::ReadExtVarint;
934 use ::std::io::Cursor;
935
936 let data = vec![0x96, 0x01, 0x7F, 0x01]; // 150, 127, 1 in varint encoding
937 let mut reader = Cursor::new(data);
938 let varints: Vec<Varint> = reader.read_varints().collect::<Result<Vec<_>>>().unwrap();
939 assert_eq!(varints.len(), 3);
940 assert_eq!(varints[0].to_uint64(), 150);
941 assert_eq!(varints[1].to_uint64(), 127);
942 assert_eq!(varints[2].to_uint64(), 1);
943 }
944
945 // ============================================================================
946 // Roundtrip tests
947 // ============================================================================
948
949 #[test]
950 fn test_write_varint_roundtrip() {
951 use super::{IteratorExtVarint, WriteExtVarint};
952
953 let test_values = vec![0, 1, 127, 128, 150, 255, 256, 65535, 0x7FFFFFFF];
954
955 for &value in &test_values {
956 // Create Varint from the test value
957 let varint = Varint::from_uint64(value);
958
959 let mut buffer = Vec::new();
960 buffer.write_varint(&varint).unwrap();
961
962 let iter = buffer.iter().copied();
963 let decoded_varint = iter.read_varint().unwrap().unwrap();
964 let decoded_value = decoded_varint.to_uint64();
965
966 assert_eq!(decoded_value, value, "Roundtrip failed for value {}", value);
967 }
968 }
969}