BytesMul 结构体
文档
介绍
对连续的内存片段的唯一引用。
BytesMut 代表了对一个潜在的共享内存区域的唯一视图。鉴于唯一性的保证,BytesMut句柄的拥有者能够改变内存。
BytesMut 可以被认为是包含一个 Buf:Arc<Vec<u8>>
,一个Buf
偏移量,一个分片长度,以及一个保证,即同一 Buf
的其他 BytesMut 不会与它的分片重叠。这个保证意味着不需要写锁。
增长: BytesMut 的 BufMut 实现将在必要时隐式地增长其缓冲区。然而,在一系列插入之前明确地预留所需的空间会更有效率。
use bytes::{BytesMut, BufMut};
let mut buf = BytesMut::with_capacity(64);
buf.put_u8(b'h');
buf.put_u8(b'e');
buf.put(&b"llo"[..]);
assert_eq!(&buf[..], b"hello");
// Freeze the buffer so that it can be shared
let a = buf.freeze();
// This does not allocate, instead `b` points to the same memory.
let b = a.clone();
assert_eq!(&a[..], b"hello");
assert_eq!(&b[..], b"hello");
源码
结构体定义
pub struct BytesMut {
ptr: NonNull<u8>,
len: usize,
cap: usize,
data: *mut Shared,
}
构造函数
with_capacity()
创建一个具有指定容量的新的BytesMut。
返回的BytesMut将能够容纳至少容量的字节而不需要重新分配。
值得注意的是,这个函数没有指定返回的BytesMut的长度,而只是指定了容量。
use bytes::{BytesMut, BufMut};
let mut bytes = BytesMut::with_capacity(64);
// `bytes` contains no data, even though there is capacity
assert_eq!(bytes.len(), 0);
bytes.put(&b"hello world"[..]);
assert_eq!(&bytes[..], b"hello world");
代码实现:
pub fn with_capacity(capacity: usize) -> BytesMut {
BytesMut::from_vec(Vec::with_capacity(capacity))
}
pub(crate) fn from_vec(mut vec: Vec<u8>) -> BytesMut {
let ptr = vptr(vec.as_mut_ptr());
let len = vec.len();
let cap = vec.capacity();
mem::forget(vec);
let original_capacity_repr = original_capacity_to_repr(cap);
let data = (original_capacity_repr << ORIGINAL_CAPACITY_OFFSET) | KIND_VEC;
BytesMut {
ptr,
len,
cap,
data: data as *mut _,
}
}
new()
创建一个新的具有默认容量的BytesMut。
结果对象的长度为0,容量未指定。该函数不进行分配。
use bytes::{BytesMut, BufMut};
let mut bytes = BytesMut::new();
assert_eq!(0, bytes.len());
bytes.reserve(2);
bytes.put_slice(b"xy");
assert_eq!(&b"xy"[..], &bytes[..]);
代码实现:
pub fn new() -> BytesMut {
// 直接 capacity = 0
BytesMut::with_capacity(0)
}
freeze()
将自己转换为一个不可变的 Bytes。
这个转换是零成本的,用来表示由句柄引用的片断将不再被改变。一旦转换完成,句柄可以被克隆并在线程间共享。
use bytes::{BytesMut, BufMut};
use std::thread;
let mut b = BytesMut::with_capacity(64);
b.put(&b"hello world"[..]);
let b1 = b.freeze();
let b2 = b1.clone();
let th = thread::spawn(move || {
assert_eq!(&b1[..], b"hello world");
});
assert_eq!(&b2[..], b"hello world");
th.join().unwrap();
split()
split_off()
在给定的索引处将字节分成两个。
之后 self包含元素 [0, at)
,而返回的 BytesMut 包含元素 [at, capacity)
。
这是一个O(1)操作,只是增加了引用计数并设置了一些索引。
use bytes::BytesMut;
let mut a = BytesMut::from(&b"hello world"[..]);
let mut b = a.split_off(5);
a[0] = b'j';
b[0] = b'!';
assert_eq!(&a[..], b"jello");
assert_eq!(&b[..], b"!world");
代码实现:
pub fn split_off(&mut self, at: usize) -> BytesMut {
assert!(
at <= self.capacity(),
"split_off out of bounds: {:?} <= {:?}",
at,
self.capacity(),
);
unsafe {
let mut other = self.shallow_clone();
other.set_start(at);
self.set_end(at);
other
}
}
split()
移除当前视图中的字节,在一个新的 BytesMut 句柄中返回。
之后,self 将是空的,但会保留操作前的任何额外容量。这与 self.split_to(self.len())
是相同的。
这是一个O(1)操作,只是增加了引用计数并设置了一些索引。
use bytes::{BytesMut, BufMut};
let mut buf = BytesMut::with_capacity(1024);
buf.put(&b"hello world"[..]);
let other = buf.split();
assert!(buf.is_empty());
assert_eq!(1013, buf.capacity());
assert_eq!(other, b"hello world"[..]);
代码实现:
pub fn split(&mut self) -> BytesMut {
let len = self.len();
self.split_to(len)
}
split_to()
在给定的索引处将缓冲区一分为二。
之后self包含元素 [at, len)
,而返回的 BytesMut 包含元素 [0, at)
。
这是一个O(1)操作,只是增加了引用计数和设置了一些索引。
use bytes::BytesMut;
let mut a = BytesMut::from(&b"hello world"[..]);
let mut b = a.split_to(5);
a[0] = b'!';
b[0] = b'j';
assert_eq!(&a[..], b"!world");
assert_eq!(&b[..], b"jello");
代码实现:
pub fn split_to(&mut self, at: usize) -> BytesMut {
assert!(
at <= self.len(),
"split_to out of bounds: {:?} <= {:?}",
at,
self.len(),
);
unsafe {
let mut other = self.shallow_clone();
other.set_end(at);
self.set_start(at);
other
}
}
truncate()
缩短缓冲区的长度,保留第一个 len 字节,放弃其余的字节。
如果 len 大于缓冲区的当前长度,则没有影响。
split_off 方法可以模拟 Truncate,但是这导致多余的字节被返回而不是丢弃。
use bytes::BytesMut;
let mut buf = BytesMut::from(&b"hello world"[..]);
buf.truncate(5);
assert_eq!(buf, b"hello"[..]);
代码实现:
pub fn truncate(&mut self, len: usize) {
if len <= self.len() {
unsafe {
self.set_len(len);
}
}
}
pub unsafe fn set_len(&mut self, len: usize) {
debug_assert!(len <= self.cap, "set_len out of bounds");
self.len = len;
}