如何对bytes crate中的BytesMut执行trim操作?
给BytesMut实现trim字节的方法
因为bytes crate的BytesMut本身没有内置的trim方法,我们可以通过扩展trait来实现这个功能,下面分两种场景给出实现:
1. Trim ASCII空白字符(对应你的示例场景)
这个实现会移除字节序列前后的ASCII空白字符(包括空格、制表符、换行符等),和Rust标准库的str::trim()行为一致:
use bytes::BytesMut; // 定义扩展trait,给BytesMut添加trim方法 trait BytesMutTrimExt { // 原地修改原BytesMut,返回自身引用 fn trim_ascii_whitespace(&mut self) -> &mut Self; // 返回新的trim后的BytesMut,不修改原实例 fn trimmed_ascii_whitespace(&self) -> BytesMut; } impl BytesMutTrimExt for BytesMut { fn trim_ascii_whitespace(&mut self) -> &mut Self { let slice = self.as_slice(); // 找到第一个非空白字节的位置,全空白则取0 let start = slice.iter().position(|&b| !b.is_ascii_whitespace()).unwrap_or(0); // 找到最后一个非空白字节的位置+1,全空白则取0 let end = slice.iter().rposition(|&b| !b.is_ascii_whitespace()).map_or(0, |pos| pos + 1); // 跳过前面的空白字节 if start > 0 { self.advance(start); } // 截断后面的空白字节 if end < self.len() { let _ = self.split_off(end - start); } self } fn trimmed_ascii_whitespace(&self) -> BytesMut { let slice = self.as_slice(); let start = slice.iter().position(|&b| !b.is_ascii_whitespace()).unwrap_or(0); let end = slice.iter().rposition(|&b| !b.is_ascii_whitespace()).map_or(0, |pos| pos + 1); // 截取子切片并转为BytesMut self.slice(start..end).into() } }
使用示例
完全匹配你的需求场景:
fn main() { // 方式1:原地修改原实例 let mut some_bytes = BytesMut::from(" hello world "); some_bytes.trim_ascii_whitespace(); assert_eq!(some_bytes, BytesMut::from("hello world")); // 方式2:返回新实例,不改动原数据 let some_bytes = BytesMut::from(" hello world "); let trim_bytes = some_bytes.trimmed_ascii_whitespace(); assert_eq!(trim_bytes, BytesMut::from("hello world")); }
2. Trim指定的单个字节
如果需要移除前后特定的字节(比如移除前后的x或0),可以实现通用的trim指定字节方法:
use bytes::BytesMut; trait BytesMutTrimExt { // 原地trim指定字节 fn trim(&mut self, byte: u8) -> &mut Self; // 返回新的trim指定字节后的BytesMut fn trimmed(&self, byte: u8) -> BytesMut; } impl BytesMutTrimExt for BytesMut { fn trim(&mut self, byte: u8) -> &mut Self { let slice = self.as_slice(); let start = slice.iter().position(|&b| b != byte).unwrap_or(0); let end = slice.iter().rposition(|&b| b != byte).map_or(0, |pos| pos + 1); if start > 0 { self.advance(start); } if end < self.len() { let _ = self.split_off(end - start); } self } fn trimmed(&self, byte: u8) -> BytesMut { let slice = self.as_slice(); let start = slice.iter().position(|&b| b != byte).unwrap_or(0); let end = slice.iter().rposition(|&b| b != byte).map_or(0, |pos| pos + 1); self.slice(start..end).into() } }
使用示例
fn main() { let mut some_bytes = BytesMut::from("xxhello worldxx"); some_bytes.trim(b'x'); assert_eq!(some_bytes, BytesMut::from("hello world")); }
边界情况说明
- 如果整个
BytesMut都是空白/指定字节,trim后会得到空的BytesMut - 方法内部使用了
BytesMut的原生方法(advance、split_off、slice),性能和原生操作一致
内容的提问来源于stack exchange,提问作者realzhujunhao
相关产品推荐
相关产品推荐

