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}