如何将实现Debug trait的值直接格式化为UTF-16字符串?
直接将实现
Debug trait的值格式化为UTF-16向量 我需要将一个实现了Debug trait的值的格式化结果编码为UTF-16码点的向量。目前的做法是先用format!宏生成UTF-8字符串,再转换为UTF-16:
use std::fmt::Debug; #[derive(Debug)] pub struct User { name: String, some_ids: [u8; 16], // 更多字段... } pub fn display_to_u16(user: &User) -> Vec<u16> { let asutf8 = format!("{user:#?}"); asutf8.encode_utf16().collect() }
但这种先转UTF-8再转UTF-16的方式存在不必要的内存开销,有没有办法直接将值格式化为UTF-16向量?
补充说明:实际场景是在实现tracing_subscriber::field::Visit::record_debug时处理抽象的dyn Debug类型,User仅作为示例。必须基于Debug trait实现,无法更换序列化方案。
解决方案:自定义Write实现流式UTF-16编码
Rust的Debug格式化是通过Write trait完成的,我们可以实现一个自定义的Write结构体,直接将输入的UTF-8字符编码为UTF-16并写入向量,跳过中间的完整UTF-8字符串分配:
use std::fmt::{self, Debug}; use std::io::Write; #[derive(Debug)] pub struct User { name: String, some_ids: [u8; 16], // 其他字段... } // 自定义Writer,内部持有UTF-16码点向量 struct Utf16Writer(Vec<u16>); impl Write for Utf16Writer { // 处理UTF-8字符串片段,直接编码为UTF-16并追加到向量 fn write_str(&mut self, s: &str) -> fmt::Result { self.0.extend(s.encode_utf16()); Ok(()) } // 优化单个字符的写入逻辑 fn write_char(&mut self, c: char) -> fmt::Result { self.0.extend(c.encode_utf16()); Ok(()) } } // 通用方法:将任意Debug值格式化为UTF-16向量 pub fn debug_to_u16<T: Debug>(value: &T) -> Vec<u16> { let mut writer = Utf16Writer(Vec::new()); // 直接调用Debug的格式化逻辑写入自定义Writer write!(writer, "{:#?}", value).expect("Debug格式化不会产生IO错误"); writer.0 } // 针对dyn Debug的使用示例 pub fn handle_dyn_debug(value: &dyn Debug) -> Vec<u16> { debug_to_u16(value) }
方案优势
- 避免了中间UTF-8字符串的内存分配和拷贝,流式处理格式化输出,内存占用更高效,尤其适合大体积的Debug输出场景。
- 完全基于
Debugtrait实现,符合需求中的约束,同时支持具体类型和dyn Debug抽象类型。
内容的提问来源于stack exchange,提问作者WorldSEnder
相关产品推荐
相关产品推荐

