pub trait AsMut<T: ?Sized> {
// Required method
fn as_mut(&mut self) -> &mut T;
}Expand description
用于进行廉价的可变到可变引用转换。
一个与 AsRef 类似的 trait,但用于在可变引用之间进行转换。如果需要进行昂贵的转换,最好用 &mut T 类型实现 From 或编写自定义函数。
注意:此 trait 一定不能失败。如果转换失败,请使用专用方法返回 Option<T> 或 Result<T, E>。
泛型实现
AsMut 自动解引用,如果内部类型是不兼容引用 (例如: 如果 foo 具有 &mut Foo 或 &mut &mut Foo 类型,foo.as_mut() 将工作相同)。
请注意,由于历史原因,上述内容目前并不适用于所有 mutably dereferenceable types,例如 foo.as_mut()不会与 Box::new(foo).as_mut() 一样工作。
相反,许多智能指针提供了一个 as_mut 实现,它简单地将一个引用返回给 pointed-to value (但不对该值执行廉价的引用 - 到 - 引用转换)。
但是,AsMut::as_mut 不应仅用于无效解引用; 可以使用 ‘Deref coercion’ 代替:
let mut x = Box::new(5i32);
// 避免这种情况:
// let y: &mut i32 = x.as_mut();
// 最好只写:
let y: &mut i32 = &mut x;Run实现 DerefMut 的类型应考虑添加 AsMut<T> 的实现,如下所示:
impl<T> AsMut<T> for SomeType
where
<SomeType as Deref>::Target: AsMut<T>,
{
fn as_mut(&mut self) -> &mut T {
self.deref_mut().as_mut()
}
}RunReflexivity
理想情况下,AsMut 将是自反的,即有一个 impl<T: ?Sized> AsMut<T> for T 与 as_mut 简单地返回其参数不变。
由于 Rust 类型系统的技术限制,目前不提供这样的一揽子实现 (它将与 &mut T where T: AsMut<U> 的另一个现有一揽子实现重叠,它允许 AsMut 自动解引用,请参见上面的 “Generic Implementations”)。
必须在需要或需要的地方为特定类型 T 显式添加 AsMut<T> for T 的简单实现。但是请注意,并非 std 中的所有类型都包含这样的实现,并且由于孤儿规则,这些类型不能由外部代码添加。
Examples
使用 AsMut 作为 trait bound 作为泛型函数,我们可以接受所有可以转换为 &mut T 类型的引用。
与只有一个 target type 的 dereference 不同,一个类型可以有多个 AsMut 实现。特别是,Vec<T> 实现了 AsMut<Vec<T>> 和 AsMut<[T]>。
在下文中,示例函数 caesar 和 null_terminate 提供了泛型接口,该接口适用于任何类型,可以通过廉价的转换为字节切片 ([u8]) 或字节 vector (Vec<u8>) 分别转换为字节切片 ([u8]) 或字节 vector (Vec<u8>)。
struct Document {
info: String,
content: Vec<u8>,
}
impl<T: ?Sized> AsMut<T> for Document
where
Vec<u8>: AsMut<T>,
{
fn as_mut(&mut self) -> &mut T {
self.content.as_mut()
}
}
fn caesar<T: AsMut<[u8]>>(data: &mut T, key: u8) {
for byte in data.as_mut() {
*byte = byte.wrapping_add(key);
}
}
fn null_terminate<T: AsMut<Vec<u8>>>(data: &mut T) {
// 使用包含大部分功能的非泛型内部函数有助于最小化单态化开销。
fn doit(data: &mut Vec<u8>) {
let len = data.len();
if len == 0 || data[len-1] != 0 {
data.push(0);
}
}
doit(data.as_mut());
}
fn main() {
let mut v: Vec<u8> = vec![1, 2, 3];
caesar(&mut v, 5);
assert_eq!(v, [6, 7, 8]);
null_terminate(&mut v);
assert_eq!(v, [6, 7, 8, 0]);
let mut doc = Document {
info: String::from("Example"),
content: vec![17, 19, 8],
};
caesar(&mut doc, 1);
assert_eq!(doc.content, [18, 20, 9]);
null_terminate(&mut doc);
assert_eq!(doc.content, [18, 20, 9, 0]);
}Run但是请注意,API 不必是泛型。在许多情况下,例如使用 &mut [u8] 或 &mut Vec<u8> 是更好的选择 (调用者需要传递正确的类型)。