Trait std::convert::AsMut

1.0.0 · source ·
pub trait AsMut<T>where
    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()
    }
}
Run

Reflexivity

理想情况下,AsMut 将是自反的,即有一个 impl<T: ?Sized> AsMut<T> for Tas_mut 简单地返回其参数不变。 由于 Rust 类型系统的技术限制,目前提供这样的一揽子实现 (它将与 &mut T where T: AsMut<U> 的另一个现有一揽子实现重叠,它允许 AsMut 自动解引用,请参见上面的 “Generic Implementations”)。

必须在需要或需要的地方为特定类型 T 显式添加 AsMut<T> for T 的简单实现。但是请注意,并非 std 中的所有类型都包含这样的实现,并且由于孤儿规则,这些类型不能由外部代码添加。

Examples

使用 AsMut 作为 trait bound 作为泛型函数,我们可以接受所有可以转换为 &mut T 类型的引用。 与只有一个 target typedereference 不同,一个类型可以有多个 AsMut 实现。特别是,Vec<T> 实现了 AsMut<Vec<T>>AsMut<[T]>

在下文中,示例函数 caesarnull_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> 是更好的选择 (调用者需要传递正确的类型)。

Required Methods§

source

fn as_mut(&mut self) -> &mut T

将此类型转换为 (通常是推断的) 输入类型的错误引用。

Implementors§

1.51.0 · source§

impl AsMut<str> for str

1.43.0 · source§

impl AsMut<str> for String

source§

impl<T> AsMut<[T]> for [T]

1.5.0 · source§

impl<T, A> AsMut<[T]> for Vec<T, A>where A: Allocator,

1.5.0 · source§

impl<T, A> AsMut<Vec<T, A>> for Vec<T, A>where A: Allocator,

1.5.0 · source§

impl<T, A> AsMut<T> for Box<T, A>where A: Allocator, T: ?Sized,

source§

impl<T, U> AsMut<U> for &mut Twhere T: AsMut<U> + ?Sized, U: ?Sized,

source§

impl<T, const N: usize> AsMut<[T; N]> for Simd<T, N>where LaneCount<N>: SupportedLaneCount, T: SimdElement,

source§

impl<T, const N: usize> AsMut<[T]> for [T; N]

source§

impl<T, const N: usize> AsMut<[T]> for Simd<T, N>where LaneCount<N>: SupportedLaneCount, T: SimdElement,