#options #no-alloc #join-handle

no-std once-option

OnceOption 类型,类似于 Option,具有一旦清空就不能重新设置以包含值的约束。对于需要在析构时消耗或无法以其他方式重新设置的成员(例如在析构时加入 JoinHandle)非常有用。

1 个不稳定版本

0.1.0 2024年3月21日

#964Rust 模式

MIT/Apache

23KB
246

once-option

CI Crates.io docs.rs Crates.io Crates.io

once_option 包定义了一个类型,OnceOption,以及它的构建辅助函数,OnceOption()

该包是 no_std

OnceOption 表示一个可选值。与 Option 不同,空的 OnceOption 不能重新设置为包含值。

此外,OnceOption 实现 DerefDerefMut,因此其内容可以不使用模式匹配(但隐式展开)来访问。

它支持与其他相同类型的 OnceOption 进行比较(PartialEqEqOrdPartialOrd),只要包含的类型也实现了这些特性。此外,如果包含的类型是 Hash,则它可以作为哈希键使用。

如果包含的类型是 Display,则它支持显示,并将所有格式化特性(除了 DebugPointer)传递给其包含的类型。

理由

OnceOption 的主要但不是唯一目的是简化和管理具有消耗值方法的成员的析构。

例如,以下代码将无法编译

// Warning: this code does *NOT* compile

use std::{thread, time::Duration};

struct SomeType {
    handle: thread::JoinHandle<u32>,
}

impl SomeType {
    fn new() -> Self {
        Self {
            handle: thread::spawn(|| {
                thread::sleep(Duration::from_secs(5));
                42
            }),
        }
    }
}

impl Drop for SomeType {
    fn drop(&mut self) {
        println!("The answer is {}", self.handle.join());
    }
}

编译器将失败并显示类似于以下错误(尝试!

Compiling playground v0.0.1 (/playground)
error[E0507]: cannot move out of `self.handle` which is behind a mutable reference
    --> src/lib.rs:22:38
     |
22   |         println!("The answer is {}", self.handle.join().unwrap());
     |                                      ^^^^^^^^^^^ ------ `self.handle` moved due to this method call
     |                                      |
     |                                      move occurs because `self.handle` has type `JoinHandle<u32>`, which does not implement the `Copy` trait
     |
note: `JoinHandle::<T>::join` takes ownership of the receiver `self`, which moves `self.handle`
    --> /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/thread/mod.rs:1649:17
     |
1649 |     pub fn join(self) -> Result<T> {
     |                 ^^^^

For more information about this error, try `rustc --explain E0507`.
error: could not compile `playground` (lib) due to 1 previous error

OnceOption 可以用来修复此问题,同时只需对代码进行最小修改

use once_option::OnceOption;
use std::{thread, time::Duration};

struct SomeType {
    handle: OnceOption<thread::JoinHandle<u32>>,
}

impl SomeType {
    fn new() -> Self {
        Self {
            handle: thread::spawn(|| {
                thread::sleep(Duration::from_secs(5));
                42
            }).into(),
        }
    }

    fn thread_id(&self) -> thread::ThreadId {
        self.handle.thread().id()
    }
}

impl Drop for SomeType {
    fn drop(&mut self) {
        println!("The answer is {}", self.handle.take().join().unwrap());
    }
}

表示

OnceOption<T>Option<T> 具有相同的 ABI;这意味着 OnceOption<T> 具有与 Option<T> 相同的大小、对齐方式和函数调用 ABI。

这一点的含义是,所有由 Option<T> 提供的 ABI 保证(即在某些条件下从 T 转换),也适用于 OnceOption<T>。有关更多详细信息,请参阅 Option 的文档

无运行时依赖