Rust in Everything
基于 bytes 1.12.1

Buf 与 BufMut

前两部分讲的是存储:Bytes 怎么共享一块内存,BytesMut 怎么往里写、怎么切出去。这一部分讲游标:读的一侧是 Buf,写的一侧是 BufMut。两个 trait 各自只要求三个方法,get_u32、put_slice、copy_to_bytes 这些几十上百个方法都是在这三个之上写的默认实现。协议解析代码写成 fn parse<B: Buf>(buf: B),就不用关心底层是一个切片、一个 Bytes,还是几段拼起来的缓冲。代码在 src/buf/ 下,两个 trait 文件的大部分篇幅是文档注释(见 源码地图)。

三章:

  1. Buf:三个必需方法的契约;chunks_vectored 的默认实现只交一段;get_* 由 buf_get_impl! 生成,当前块够长时直接转换,跨块时拷进临时数组;数据不够时 panic,try_get_*(1.10.0)返回 TryGetError;copy_to_bytes 默认分配一次,Bytes / BytesMut 把它覆盖成 split_to。
  2. BufMut 与 UninitSlice:chunk_mut 交出的是 &mut UninitSlice 而不是 &mut [u8],advance_mut 是 unsafe;put 和 Vec<u8> 的写入路径。
  3. 适配器: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 的解码与编码)。

💬 关联讨论

发起讨论
加载中...