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