1 个不稳定版本
0.1.7 | 2020年8月14日 |
---|---|
0.1.6 |
|
0.1.5 |
|
0.1.4 |
|
0.1.2 |
|
#74 在 Rust 模式 中
83,076 每月下载量
在 164 个 包中使用 (37 个直接使用)
27KB
187 行
replace_with
暂时获取可变位置上的值的所有权,并根据旧值替换为新值。
此包提供了函数 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() -> T
panic,则确实会终止。使用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_with
与no_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 License, Version 2.0, (LICENSE-APACHE.txt 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT.txt 或 http://opensource.org/licenses/MIT)
由你选择。
除非你明确表示,否则根据 Apache-2.0 许可证定义,你提交的任何有意包含在作品中的贡献都将根据上述协议双重许可,不附加任何其他条款或条件。