Skip to main content

qubit_io/codecs/
leb128_writer.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10use std::io::{
11    Result,
12    Seek,
13    SeekFrom,
14    Write,
15};
16
17use crate::{
18    Leb128WriteExt,
19    StringWriteExt,
20};
21
22/// Writer wrapper for LEB128 integers and LEB128 length-prefixed strings.
23///
24/// # Examples
25/// ```
26/// use qubit_io::Leb128Writer;
27///
28/// let mut output = Leb128Writer::new(Vec::new());
29/// output.write_u16(300)?;
30///
31/// assert_eq!(vec![0xac, 0x02], output.into_inner());
32/// # Ok::<(), std::io::Error>(())
33/// ```
34pub struct Leb128Writer<W> {
35    inner: W,
36}
37
38impl<W> Leb128Writer<W> {
39    /// Creates a LEB128 writer.
40    ///
41    /// # Parameters
42    /// - `inner`: Writer to wrap.
43    ///
44    /// # Returns
45    /// A new LEB128 writer.
46    #[inline]
47    pub fn new(inner: W) -> Self {
48        Self { inner }
49    }
50
51    /// Returns an immutable reference to the wrapped writer.
52    ///
53    /// # Returns
54    /// The wrapped writer reference.
55    #[inline]
56    pub fn get_ref(&self) -> &W {
57        &self.inner
58    }
59
60    /// Returns a mutable reference to the wrapped writer.
61    ///
62    /// # Returns
63    /// The wrapped writer reference.
64    #[inline]
65    pub fn get_mut(&mut self) -> &mut W {
66        &mut self.inner
67    }
68
69    /// Consumes this wrapper and returns the wrapped writer.
70    ///
71    /// # Returns
72    /// The wrapped writer.
73    #[inline]
74    pub fn into_inner(self) -> W {
75        self.inner
76    }
77}
78
79macro_rules! delegate_write {
80    ($name:ident, $inner:ident, $value:ty) => {
81        #[doc = concat!("Writes a LEB128 `", stringify!($value), "`.")]
82        ///
83        /// # Parameters
84        /// - `value`: Value to encode.
85        ///
86        /// # Errors
87        /// Returns an I/O error from the wrapped writer.
88        #[inline]
89        pub fn $name(&mut self, value: $value) -> Result<()> {
90            self.inner.$inner(value)
91        }
92    };
93}
94
95impl<W> Leb128Writer<W>
96where
97    W: Write,
98{
99    delegate_write!(write_u8, write_uleb_u8, u8);
100    delegate_write!(write_u16, write_uleb_u16, u16);
101    delegate_write!(write_u32, write_uleb_u32, u32);
102    delegate_write!(write_u64, write_uleb_u64, u64);
103    delegate_write!(write_u128, write_uleb_u128, u128);
104    delegate_write!(write_usize, write_uleb_usize, usize);
105    delegate_write!(write_i8, write_sleb_i8, i8);
106    delegate_write!(write_i16, write_sleb_i16, i16);
107    delegate_write!(write_i32, write_sleb_i32, i32);
108    delegate_write!(write_i64, write_sleb_i64, i64);
109    delegate_write!(write_i128, write_sleb_i128, i128);
110    delegate_write!(write_isize, write_sleb_isize, isize);
111
112    /// Writes a UTF-8 string with an unsigned LEB128 byte-length prefix.
113    ///
114    /// # Parameters
115    /// - `value`: String slice to write.
116    ///
117    /// # Errors
118    /// Returns an I/O error from the wrapped writer.
119    #[inline]
120    pub fn write_utf8_string(&mut self, value: &str) -> Result<()> {
121        self.inner.write_utf8_string_uleb(value)
122    }
123}
124
125impl<W> Write for Leb128Writer<W>
126where
127    W: Write,
128{
129    #[inline]
130    fn write(&mut self, buffer: &[u8]) -> Result<usize> {
131        self.inner.write(buffer)
132    }
133
134    #[inline]
135    fn flush(&mut self) -> Result<()> {
136        self.inner.flush()
137    }
138}
139
140impl<W> Seek for Leb128Writer<W>
141where
142    W: Seek,
143{
144    #[inline]
145    fn seek(&mut self, position: SeekFrom) -> Result<u64> {
146        self.inner.seek(position)
147    }
148}