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}