Skip to main content

qubit_io/ext/
string_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::util::{
16    write_utf8_payload as write_utf8_payload_impl,
17    write_utf8_string_with_u16_len,
18    write_utf8_string_with_u32_len,
19};
20use crate::{
21    BinaryWriteExt,
22    ByteOrder,
23    Leb128WriteExt,
24};
25
26/// Extension methods for writing length-prefixed UTF-8 strings.
27pub trait StringWriteExt: Write {
28    /// Writes a UTF-8 payload without a length prefix.
29    ///
30    /// # Parameters
31    /// - `value`: String slice to write.
32    ///
33    /// # Errors
34    /// Returns an I/O error from the underlying writer.
35    fn write_utf8_payload(&mut self, value: &str) -> Result<()>;
36
37    /// Writes a UTF-8 string with an unsigned LEB128 byte-length prefix.
38    ///
39    /// The length prefix is encoded as `usize`, so this format is target-width
40    /// dependent. Prefer `u16` or `u32` length-prefix methods for persistent
41    /// files and cross-platform protocols.
42    ///
43    /// # Parameters
44    /// - `value`: String slice to write.
45    ///
46    /// # Errors
47    /// Returns an I/O error from the underlying writer.
48    fn write_utf8_string_uleb(&mut self, value: &str) -> Result<()>;
49
50    /// Writes a UTF-8 string with a runtime-order `u16` byte-length prefix.
51    ///
52    /// # Parameters
53    /// - `value`: String slice to write.
54    /// - `byte_order`: Byte order used by the length prefix.
55    ///
56    /// # Errors
57    /// Returns [`std::io::ErrorKind::InvalidInput`] when the UTF-8 byte length does not
58    /// fit into `u16`, or an I/O error from the underlying writer.
59    fn write_utf8_string_u16(&mut self, value: &str, byte_order: ByteOrder) -> Result<()>;
60
61    /// Writes a UTF-8 string with a big-endian `u16` byte-length prefix.
62    ///
63    /// # Parameters
64    /// - `value`: String slice to write.
65    ///
66    /// # Errors
67    /// Returns [`std::io::ErrorKind::InvalidInput`] when the UTF-8 byte length does not
68    /// fit into `u16`, or an I/O error from the underlying writer.
69    fn write_utf8_string_u16_be(&mut self, value: &str) -> Result<()>;
70
71    /// Writes a UTF-8 string with a little-endian `u16` byte-length prefix.
72    ///
73    /// # Parameters
74    /// - `value`: String slice to write.
75    ///
76    /// # Errors
77    /// Returns [`std::io::ErrorKind::InvalidInput`] when the UTF-8 byte length does not
78    /// fit into `u16`, or an I/O error from the underlying writer.
79    fn write_utf8_string_u16_le(&mut self, value: &str) -> Result<()>;
80
81    /// Writes a UTF-8 string with a runtime-order `u32` byte-length prefix.
82    ///
83    /// # Parameters
84    /// - `value`: String slice to write.
85    /// - `byte_order`: Byte order used by the length prefix.
86    ///
87    /// # Errors
88    /// Returns [`std::io::ErrorKind::InvalidInput`] when the UTF-8 byte length does not
89    /// fit into `u32`, or an I/O error from the underlying writer.
90    fn write_utf8_string_u32(&mut self, value: &str, byte_order: ByteOrder) -> Result<()>;
91
92    /// Writes a UTF-8 string with a big-endian `u32` byte-length prefix.
93    ///
94    /// # Parameters
95    /// - `value`: String slice to write.
96    ///
97    /// # Errors
98    /// Returns [`std::io::ErrorKind::InvalidInput`] when the UTF-8 byte length does not
99    /// fit into `u32`, or an I/O error from the underlying writer.
100    fn write_utf8_string_u32_be(&mut self, value: &str) -> Result<()>;
101
102    /// Writes a UTF-8 string with a little-endian `u32` byte-length prefix.
103    ///
104    /// # Parameters
105    /// - `value`: String slice to write.
106    ///
107    /// # Errors
108    /// Returns [`std::io::ErrorKind::InvalidInput`] when the UTF-8 byte length does not
109    /// fit into `u32`, or an I/O error from the underlying writer.
110    fn write_utf8_string_u32_le(&mut self, value: &str) -> Result<()>;
111}
112
113impl<T> StringWriteExt for T
114where
115    T: Write + ?Sized,
116{
117    #[inline]
118    fn write_utf8_payload(&mut self, value: &str) -> Result<()> {
119        write_utf8_payload_impl(self, value)
120    }
121
122    #[inline]
123    fn write_utf8_string_uleb(&mut self, value: &str) -> Result<()> {
124        let bytes = value.as_bytes();
125        self.write_uleb_usize(bytes.len())?;
126        self.write_all(bytes)
127    }
128
129    #[inline]
130    fn write_utf8_string_u16(&mut self, value: &str, byte_order: ByteOrder) -> Result<()> {
131        write_utf8_string_with_u16_len(self, value, |writer, len| writer.write_u16(len, byte_order))
132    }
133
134    #[inline]
135    fn write_utf8_string_u16_be(&mut self, value: &str) -> Result<()> {
136        write_utf8_string_with_u16_len(self, value, |writer, len| writer.write_u16_be(len))
137    }
138
139    #[inline]
140    fn write_utf8_string_u16_le(&mut self, value: &str) -> Result<()> {
141        write_utf8_string_with_u16_len(self, value, |writer, len| writer.write_u16_le(len))
142    }
143
144    #[inline]
145    fn write_utf8_string_u32(&mut self, value: &str, byte_order: ByteOrder) -> Result<()> {
146        write_utf8_string_with_u32_len(self, value, |writer, len| writer.write_u32(len, byte_order))
147    }
148
149    #[inline]
150    fn write_utf8_string_u32_be(&mut self, value: &str) -> Result<()> {
151        write_utf8_string_with_u32_len(self, value, |writer, len| writer.write_u32_be(len))
152    }
153
154    #[inline]
155    fn write_utf8_string_u32_le(&mut self, value: &str) -> Result<()> {
156        write_utf8_string_with_u32_len(self, value, |writer, len| writer.write_u32_le(len))
157    }
158}