为何缓冲区总是以&mut [u8]传递而非&mut [MaybeUninit<u8>]?
关于Rust中接收缓冲区初始化的优化思考
我见过一种很常见的Rust接收数据模式:
let receiver: Receiver = ...; let mut buf = [0; 1024]; // 分配一个肯定过大的缓冲区 let bytes_received = receiver.recv(&mut buf);
要访问接收到的数据,通常会这么做:
let data = buf[0..bytes_received];
这种模式本身没什么问题,但我在意的是——我们总是要把整个数组清零,可实际上根本没必要这么做。虽然这算不上高开销操作,但一直无视这个冗余步骤总觉得不太合理。
为此我提出了一种替代方案:
use std::mem::{MaybeUninit, transmute}; struct Receiver { // 仅作演示用 data: &'static str, } trait Receive { // 只需要实现这个方法,`recv`可以基于它自动派生 fn recv_maybe_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> &[u8]; fn recv(&mut self, buf: &mut [u8]) -> usize { self.recv_maybe_uninit(unsafe { transmute(buf) }).len() } } impl Receive for Receiver { fn recv_maybe_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> &[u8] { for (i, byte) in self.data.as_bytes().iter().enumerate() { buf[i] = MaybeUninit::<u8>::new(*byte); if i == buf.len() { return unsafe { transmute(buf) } } } unsafe { transmute(&buf[0..self.data.as_bytes().len()]) } } } fn main() { let mut receiver = Receiver { data: "Hello, world!", }; let mut buf = [MaybeUninit::uninit(); 1024]; let data = receiver.recv_maybe_uninit(&mut buf); println!("{:?}", std::str::from_utf8(data).unwrap()); }
如果把recv_maybe_uninit设为特质的默认方法,就能轻松派生出recv方法!当然,或许还有更好的实现思路——比如让缓冲区实现一个支持写入u8的特质……
那么问题来了:这种写法为什么没有被广泛采用呢?
内容的提问来源于stack exchange,提问作者doliphin
相关产品推荐
相关产品推荐

