Skip to main content

qubit_io/ext/
zig_zag_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    NonStrict,
18    ZigZagCodec,
19};
20
21macro_rules! write_zig_zag_value {
22    ($writer:expr, $value:expr, $ty:ty) => {
23        write_zig_zag::<{ ZigZagCodec::<$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 { ZigZagCodec::<$ty, NonStrict>::write_unchecked(bytes, 0, value) }
29            },
30        )
31    };
32}
33
34/// Extension methods for writing ZigZag + unsigned LEB128 integers.
35///
36/// # Target-width integers
37///
38/// `isize` methods use the current Rust target's pointer width. Prefer
39/// fixed-width integer methods such as [`Self::write_zig_zag_i64`] for
40/// persistent files and cross-platform protocols.
41pub trait ZigZagWriteExt: Write {
42    /// Writes a ZigZag `i8`.
43    #[inline]
44    fn write_zig_zag_i8(&mut self, value: i8) -> Result<()> {
45        write_zig_zag_value!(self, value, i8)
46    }
47
48    /// Writes a ZigZag `i16`.
49    #[inline]
50    fn write_zig_zag_i16(&mut self, value: i16) -> Result<()> {
51        write_zig_zag_value!(self, value, i16)
52    }
53
54    /// Writes a ZigZag `i32`.
55    #[inline]
56    fn write_zig_zag_i32(&mut self, value: i32) -> Result<()> {
57        write_zig_zag_value!(self, value, i32)
58    }
59
60    /// Writes a ZigZag `i64`.
61    #[inline]
62    fn write_zig_zag_i64(&mut self, value: i64) -> Result<()> {
63        write_zig_zag_value!(self, value, i64)
64    }
65
66    /// Writes a ZigZag `i128`.
67    #[inline]
68    fn write_zig_zag_i128(&mut self, value: i128) -> Result<()> {
69        write_zig_zag_value!(self, value, i128)
70    }
71
72    /// Writes a ZigZag `isize`.
73    #[inline]
74    fn write_zig_zag_isize(&mut self, value: isize) -> Result<()> {
75        write_zig_zag_value!(self, value, isize)
76    }
77}
78
79impl<W> ZigZagWriteExt for W where W: Write + ?Sized {}
80
81#[inline]
82fn write_zig_zag<const N: usize, T, W, F>(writer: &mut W, value: T, encode: F) -> Result<()>
83where
84    W: Write + ?Sized,
85    F: FnOnce(&mut [u8], T) -> usize,
86{
87    let mut bytes = [0u8; N];
88    let len = encode(&mut bytes, value);
89    writer.write_all(&bytes[..len])
90}