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 ******************************************************************************/
10use std::io::{
11 Result,
12 Write,
13};
14
15use crate::Leb128WriteExt;
16
17/// Extension methods for writing ZigZag encoded signed integers.
18///
19/// ZigZag maps signed integers to unsigned integers so small negative values
20/// still have short varint encodings. The mapped unsigned value is written with
21/// unsigned LEB128. The ZigZag mapping follows the Protocol Buffers encoding
22/// guide:
23/// <https://protobuf.dev/programming-guides/encoding/#signed-integers>.
24pub trait ZigZagWriteExt: Write {
25 /// Writes a ZigZag encoded `i8`.
26 ///
27 /// # Parameters
28 /// - `value`: Value to encode.
29 ///
30 /// # Errors
31 /// Returns an I/O error from the underlying writer.
32 fn write_zigzag_i8(&mut self, value: i8) -> Result<()>;
33
34 /// Writes a ZigZag encoded `i16`.
35 ///
36 /// # Parameters
37 /// - `value`: Value to encode.
38 ///
39 /// # Errors
40 /// Returns an I/O error from the underlying writer.
41 fn write_zigzag_i16(&mut self, value: i16) -> Result<()>;
42
43 /// Writes a ZigZag encoded `i32`.
44 ///
45 /// # Parameters
46 /// - `value`: Value to encode.
47 ///
48 /// # Errors
49 /// Returns an I/O error from the underlying writer.
50 fn write_zigzag_i32(&mut self, value: i32) -> Result<()>;
51
52 /// Writes a ZigZag encoded `i64`.
53 ///
54 /// # Parameters
55 /// - `value`: Value to encode.
56 ///
57 /// # Errors
58 /// Returns an I/O error from the underlying writer.
59 fn write_zigzag_i64(&mut self, value: i64) -> Result<()>;
60
61 /// Writes a ZigZag encoded `i128`.
62 ///
63 /// # Parameters
64 /// - `value`: Value to encode.
65 ///
66 /// # Errors
67 /// Returns an I/O error from the underlying writer.
68 fn write_zigzag_i128(&mut self, value: i128) -> Result<()>;
69
70 /// Writes a ZigZag encoded `isize`.
71 ///
72 /// # Parameters
73 /// - `value`: Value to encode.
74 ///
75 /// # Errors
76 /// Returns an I/O error from the underlying writer.
77 fn write_zigzag_isize(&mut self, value: isize) -> Result<()>;
78}
79
80impl<T> ZigZagWriteExt for T
81where
82 T: Write + ?Sized,
83{
84 #[inline]
85 fn write_zigzag_i8(&mut self, value: i8) -> Result<()> {
86 self.write_uleb_u8(encode_zigzag_i8(value))
87 }
88
89 #[inline]
90 fn write_zigzag_i16(&mut self, value: i16) -> Result<()> {
91 self.write_uleb_u16(encode_zigzag_i16(value))
92 }
93
94 #[inline]
95 fn write_zigzag_i32(&mut self, value: i32) -> Result<()> {
96 self.write_uleb_u32(encode_zigzag_i32(value))
97 }
98
99 #[inline]
100 fn write_zigzag_i64(&mut self, value: i64) -> Result<()> {
101 self.write_uleb_u64(encode_zigzag_i64(value))
102 }
103
104 #[inline]
105 fn write_zigzag_i128(&mut self, value: i128) -> Result<()> {
106 self.write_uleb_u128(encode_zigzag_i128(value))
107 }
108
109 #[inline]
110 fn write_zigzag_isize(&mut self, value: isize) -> Result<()> {
111 self.write_uleb_usize(encode_zigzag_isize(value))
112 }
113}
114
115/// Encodes an `i8` with ZigZag mapping.
116///
117/// # Parameters
118/// - `value`: Signed value to map.
119///
120/// # Returns
121/// ZigZag mapped unsigned value.
122fn encode_zigzag_i8(value: i8) -> u8 {
123 ((value as u8) << 1) ^ ((value >> 7) as u8)
124}
125
126/// Encodes an `i16` with ZigZag mapping.
127///
128/// # Parameters
129/// - `value`: Signed value to map.
130///
131/// # Returns
132/// ZigZag mapped unsigned value.
133fn encode_zigzag_i16(value: i16) -> u16 {
134 ((value as u16) << 1) ^ ((value >> 15) as u16)
135}
136
137/// Encodes an `i32` with ZigZag mapping.
138///
139/// # Parameters
140/// - `value`: Signed value to map.
141///
142/// # Returns
143/// ZigZag mapped unsigned value.
144fn encode_zigzag_i32(value: i32) -> u32 {
145 ((value as u32) << 1) ^ ((value >> 31) as u32)
146}
147
148/// Encodes an `i64` with ZigZag mapping.
149///
150/// # Parameters
151/// - `value`: Signed value to map.
152///
153/// # Returns
154/// ZigZag mapped unsigned value.
155fn encode_zigzag_i64(value: i64) -> u64 {
156 ((value as u64) << 1) ^ ((value >> 63) as u64)
157}
158
159/// Encodes an `i128` with ZigZag mapping.
160///
161/// # Parameters
162/// - `value`: Signed value to map.
163///
164/// # Returns
165/// ZigZag mapped unsigned value.
166fn encode_zigzag_i128(value: i128) -> u128 {
167 ((value as u128) << 1) ^ ((value >> 127) as u128)
168}
169
170/// Encodes an `isize` with ZigZag mapping.
171///
172/// # Parameters
173/// - `value`: Signed value to map.
174///
175/// # Returns
176/// ZigZag mapped unsigned value.
177fn encode_zigzag_isize(value: isize) -> usize {
178 ((value as usize) << 1) ^ ((value >> (isize::BITS - 1)) as usize)
179}