#value #replace #mutability #mutable #temporarily #location #ownership

no-std replace_with

暂时获取可变位置上的值的所有权,并根据旧值替换为新值

1 个不稳定版本

0.1.7 2020年8月14日
0.1.6 2020年7月18日
0.1.5 2019年10月17日
0.1.4 2019年9月1日
0.1.2 2018年11月27日

#74Rust 模式

Download history 20936/week @ 2024-03-14 17016/week @ 2024-03-21 19309/week @ 2024-03-28 20201/week @ 2024-04-04 27228/week @ 2024-04-11 17454/week @ 2024-04-18 16679/week @ 2024-04-25 18801/week @ 2024-05-02 19298/week @ 2024-05-09 20174/week @ 2024-05-16 15608/week @ 2024-05-23 19776/week @ 2024-05-30 20193/week @ 2024-06-06 26573/week @ 2024-06-13 19287/week @ 2024-06-20 13233/week @ 2024-06-27

83,076 每月下载量
164 包中使用 (37 个直接使用)

MIT/Apache

27KB
187

replace_with

Crates.io MIT / Apache 2.0 licensed Build Status

📖 文档 | 💬 聊天

暂时获取可变位置上的值的所有权,并根据旧值替换为新值。

此包提供了函数 replace_with(),类似于 std::mem::replace(),但它允许替换值从原始值映射。

有关其优点的讨论,请参阅 RFC 1736。它从未合并,并且所需的从 &mut T 暂时移动的能力尚不存在,因此此包是我的临时解决方案。

这与take_mut非常相似,不过使用了Drop而不是std::panic::catch_unwind()来响应堆栈展开,从而避免了调用extern "C" __rust_maybe_catch_panic()带来的优化屏障。因此,它比之前的实现快∞倍。API还尝试使在panic情况下的行为更加明确——replace_with()接受两个闭包,从而避免了在“标准情况”下(映射闭包FnOnce(T) -> T会panic,就像take_mut::take()一样)终止。然而,如果第二个闭包FnOnce() -> Tpanic,则确实会终止。使用replace_with_or_abort()可以获取“第一次panic时终止”的行为。

示例

考虑这个激励示例

enum States {
    A(String),
    B(String),
}

impl States {
    fn poll(&mut self) {
        // error[E0507]: cannot move out of borrowed content
        *self = match *self {
            //        ^^^^^ cannot move out of borrowed content
            States::A(a) => States::B(a),
            States::B(a) => States::A(a),
        };
    }
}

根据上下文,这可能相当难以解决。然而,使用这个crate

enum States {
    A(String),
    B(String),
}

impl States {
    fn poll(&mut self) {
        replace_with_or_abort(self, |self_| match self_ {
            States::A(a) => States::B(a),
            States::B(a) => States::A(a),
        });
    }
}

太棒了!

no_std

要使用replace_withno_std,您必须通过指定依赖关系来禁用默认启用的std功能,如下所示

# Cargo.toml

[dependencies.replace_with]
version = ...
default-features = false
features = []
...

replace_with()replace_with_or_default()函数在稳定版Rust中,无论是否使用std都可用。

然而,默认情况下,replace_with_or_abort()函数使用std::process::abort(),这在no_std中不可用。

因此,默认情况下,replace_with会调用core::intrinsics::abort(),这反过来又需要nightly Rust。

对于稳定的no_std来说,并非所有事情都失去了,replace_with还有一招

panic = "abort"

如果你在 crate 的 Cargo.toml 文件的 [profile] 部分中定义了 panic = abort ...

# Cargo.toml

[profile.debug]
panic = "abort"

[profile.release]
panic = "abort"

… 并在你的 crate 的 Cargo.toml 文件的 dependencies 部分添加了 "panic_abort" 功能到 replace_with ...

# Cargo.toml

[dependencies.replace_with]
features = ["panic_abort"]
...

… 那么 "panic_abort" 功能将启用 replace_with_or_abort_unchecked() 函数,它在稳定版 Rust 中作为一个 unsafe 函数,简单地包装了 ptr::write(dest, f(ptr::read(dest)));.

注意:只有在你定义了 panic = "abort" 的情况下才能使用此函数,否则可能会发生不良后果。你必须 确保 维护此不变性!

许可协议

许可协议为以下之一:

由你选择。

除非你明确表示,否则根据 Apache-2.0 许可证定义,你提交的任何有意包含在作品中的贡献都将根据上述协议双重许可,不附加任何其他条款或条件。

无运行时依赖

功能