Skip to main content

qubit_io/ext/
leb128_write_ext.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 ******************************************************************************/
10
11use std::io::{
12    Result,
13    Write,
14};
15
16use crate::codec::{
17    Leb128Codec,
18    NonStrict,
19};
20
21macro_rules! write_leb128_value {
22    ($writer:expr, $value:expr, $ty:ty) => {
23        write_leb128::<{ Leb128Codec::<$ty, NonStrict>::REQUIRED_MIN_BUFFER_LEN }, _, _, _>(
24            $writer,
25            $value,
26            |bytes, value| {
27                // SAFETY: The local buffer is exactly the codec's minimum buffer length.
28                unsafe { Leb128Codec::<$ty, NonStrict>::write_unchecked(bytes, 0, value) }
29            },
30        )
31    };
32}
33
34/// Extension methods for writing canonical LEB128 integers to byte streams.
35///
36/// # Target-width integers
37///
38/// `usize` and `isize` methods use the current Rust target's pointer width.
39/// Prefer fixed-width integer methods such as [`Self::write_uleb_u64`] or
40/// [`Self::write_sleb_i64`] for persistent files and cross-platform protocols.
41pub trait Leb128WriteExt: Write {
42    /// Writes an unsigned LEB128 `u8`.
43    #[inline]
44    fn write_uleb_u8(&mut self, value: u8) -> Result<()> {
45        write_leb128_value!(self, value, u8)
46    }
47
48    /// Writes an unsigned LEB128 `u16`.
49    #[inline]
50    fn write_uleb_u16(&mut self, value: u16) -> Result<()> {
51        write_leb128_value!(self, value, u16)
52    }
53
54    /// Writes an unsigned LEB128 `u32`.
55    #[inline]
56    fn write_uleb_u32(&mut self, value: u32) -> Result<()> {
57        write_leb128_value!(self, value, u32)
58    }
59
60    /// Writes an unsigned LEB128 `u64`.
61    #[inline]
62    fn write_uleb_u64(&mut self, value: u64) -> Result<()> {
63        write_leb128_value!(self, value, u64)
64    }
65
66    /// Writes an unsigned LEB128 `u128`.
67    #[inline]
68    fn write_uleb_u128(&mut self, value: u128) -> Result<()> {
69        write_leb128_value!(self, value, u128)
70    }
71
72    /// Writes an unsigned LEB128 `usize`.
73    #[inline]
74    fn write_uleb_usize(&mut self, value: usize) -> Result<()> {
75        write_leb128_value!(self, value, usize)
76    }
77
78    /// Writes a signed LEB128 `i8`.
79    #[inline]
80    fn write_sleb_i8(&mut self, value: i8) -> Result<()> {
81        write_leb128_value!(self, value, i8)
82    }
83
84    /// Writes a signed LEB128 `i16`.
85    #[inline]
86    fn write_sleb_i16(&mut self, value: i16) -> Result<()> {
87        write_leb128_value!(self, value, i16)
88    }
89
90    /// Writes a signed LEB128 `i32`.
91    #[inline]
92    fn write_sleb_i32(&mut self, value: i32) -> Result<()> {
93        write_leb128_value!(self, value, i32)
94    }
95
96    /// Writes a signed LEB128 `i64`.
97    #[inline]
98    fn write_sleb_i64(&mut self, value: i64) -> Result<()> {
99        write_leb128_value!(self, value, i64)
100    }
101
102    /// Writes a signed LEB128 `i128`.
103    #[inline]
104    fn write_sleb_i128(&mut self, value: i128) -> Result<()> {
105        write_leb128_value!(self, value, i128)
106    }
107
108    /// Writes a signed LEB128 `isize`.
109    #[inline]
110    fn write_sleb_isize(&mut self, value: isize) -> Result<()> {
111        write_leb128_value!(self, value, isize)
112    }
113}
114
115impl<W> Leb128WriteExt for W where W: Write + ?Sized {}
116
117#[inline]
118fn write_leb128<const N: usize, T, W, F>(writer: &mut W, value: T, encode: F) -> Result<()>
119where
120    W: Write + ?Sized,
121    F: FnOnce(&mut [u8], T) -> usize,
122{
123    let mut bytes = [0u8; N];
124    let len = encode(&mut bytes, value);
125    writer.write_all(&bytes[..len])
126}