如何将&mut BytesMut传递给接收&Bytes参数的函数?
如何将
&mut BytesMut传递给接收&Bytes参数的函数? 嗨,这个问题我之前也碰到过,给你说几个实用的解决办法,看你需求选就行~
首先得搞清楚:BytesMut 是可变的字节缓冲区,Bytes 是不可变的、可安全共享的字节容器,两者都是bytes工具集里的类型,但直接传&mut BytesMut给要&Bytes的函数肯定是不行的,得做些转换。
方法一:冻结BytesMut得到Bytes(一次性使用场景)
如果你的BytesMut用完这次就不需要再修改或者使用了,那直接用freeze()方法就搞定了:
let mut buf = BytesMut::from(&b"hello world"[..]); // 调用freeze()消耗掉buf,得到Bytes let bytes = buf.freeze(); parse_len(&bytes); // 注意:这里buf已经不能再用了,因为已经被冻结消耗了
这个方法没有复制开销,但是代价是原BytesMut就废了,适合你处理完这部分内容就不再需要原缓冲区的场景。
方法二:复制内容生成临时Bytes(需要保留原BytesMut的场景)
如果你之后还要继续操作原来的BytesMut,那可以先把它的内容复制一份,用副本生成Bytes:
let mut buf = BytesMut::from(&b"hello world"[..]); // 从buf的内容复制出一份Bytes let temp_bytes = Bytes::copy_from_slice(&buf); parse_len(&temp_bytes); // 这里buf还能继续用,比如继续写入数据 buf.extend_from_slice(&b" more data"[..]);
不过这个方法会有数据复制的开销,如果你的数据量特别大,可能会影响性能,得权衡着用。
方法三:修改目标函数的参数类型(最优解,推荐!)
其实最省事的办法是直接改parse_len的参数,把&Bytes改成&[u8]。因为不管是Bytes还是BytesMut,都能自动解引用成&[u8],这样函数的通用性一下子就上去了,不管传&Bytes、&BytesMut甚至直接传普通的&[u8]都能兼容:
// 修改后的函数 fn parse_len(bytes: &[u8]) -> usize { // 原来的逻辑完全不用改,比如取第一个字节判断类型,后面的解析长度 let msg_type = bytes[0]; // 假设长度是后面4个字节转成usize let len_bytes = &bytes[1..5]; u32::from_be_bytes(len_bytes.try_into().unwrap()) as usize } // 调用的时候直接传&mut buf或者&buf都可以 let mut buf = BytesMut::from(&b"\x01\x00\x00\x00\x0ahello"[..]); parse_len(&buf); // 直接传&BytesMut就行 // 传&Bytes也照样能用 let bytes = Bytes::from(&b"\x02\x00\x00\x00\x05world"[..]); parse_len(&bytes);
这个方法既没有复制开销,又不用做各种转换,简直是一劳永逸的办法,强烈推荐!
备注:内容来源于stack exchange,提问作者ivanbgd
相关产品推荐
相关产品推荐

