Buf 与 BufMut
前两部分讲的是存储:Bytes 怎么共享一块内存,BytesMut 怎么往里写、怎么切出去。这一部分讲游标:读的一侧是 Buf,写的一侧是 BufMut。两个 trait 各自只要求三个方法,get_u32、put_slice、copy_to_bytes 这些几十上百个方法都是在这三个之上写的默认实现。协议解析代码写成 fn parse<B: Buf>(buf: B),就不用关心底层是一个切片、一个 Bytes,还是几段拼起来的缓冲。代码在 src/buf/ 下,两个 trait 文件的大部分篇幅是文档注释(见 源码地图)。
三章:
- Buf:三个必需方法的契约;
chunks_vectored的默认实现只交一段;get_*由buf_get_impl!生成,当前块够长时直接转换,跨块时拷进临时数组;数据不够时 panic,try_get_*(1.10.0)返回TryGetError;copy_to_bytes默认分配一次,Bytes/BytesMut把它覆盖成split_to。 - BufMut 与 UninitSlice:
chunk_mut交出的是&mut UninitSlice而不是&mut [u8],advance_mut是unsafe;put和Vec<u8>的写入路径。 - 适配器:
Chain、Take、Limit、Reader/Writer、IntoIter,每个只改几个方法。
flowchart TB src["Bytes / BytesMut / 切片"] --> rd["Buf:读游标"] rd --> getn["get_* / copy_to_bytes"] rd --> ad["Chain / Take / Reader"] ad --> rd dst["BytesMut / Vec u8"] --> wr["BufMut:写游标"] wr --> putn["put_* / chunk_mut"] wr --> lim["Limit / Writer"] lim --> wr
谁在用:hyper 的读缓冲用 BufMut 的 chunk_mut 把未初始化的尾部交给 socket(读写缓冲),写出时把响应头和 body 用 Chain 串起来、chunks_vectored 交给 writev(body 的解码与编码)。
💬 关联讨论
发起讨论加载中...