#refcell #rc #cell #options #data-structures

rco-cell

为Rc>>及其弱变体提供包装。包含在此类数据结构上通常执行的各种实用程序。

1 个不稳定版本

0.1.0 2024年3月2日

#284 in 内存管理

MIT/Apache

47KB
863

RcOCell

Rc<RefCell<Option<T>>>及其弱变体提供包装。

包含在此类数据结构上通常执行的各种实用程序。

简单示例

pub fn main() {
    let cell : RcOCell<u8> = RcOCell::from_value(1u8);
    
    //The usual RefCell stuff...
    let borrowed : Ref<u8> = cell.borrow();
    //...
    drop(borrowed);
    let borrowed_mut : RefMut<u8> = cell.borrow_mut();
    //...
    drop(borrowed_mut);
    
   
}

信息

以下函数作为RcoCell和WeakRcoCell的一部分提供

一般来说,所有以"try"开头的前缀函数都不会panic。所有没有此前缀的函数可能会panic,具体取决于它们所做的工作。

借用

  • borrowborrow_mut
    • 就像RefCell一样
  • try_borrowtry_borrow_mut
    • 就像RefCell一样,但错误类型是一个枚举。

这些调用要么panic,要么在单元格为空时失败。正常的Rust借用规则适用:只有1个可变借用或n个普通借用。如果在运行时违反借用规则,则要么panic,要么失败。

修改

  • settry_set
    • 设置值并返回一个Option作为前一个值
    • 如果值被借用,则不起作用。
  • replacetry_replace
    • 设置值,直接返回前一个值。
    • 在空单元格上不起作用。
    • 如果值被借用,则不起作用。
  • cleartry_clear
    • 清除值并返回一个Option作为前一个值
    • 如果值被借用,则不起作用。
  • get_and_cleartry_get_and_clear
    • 清除值并直接返回前一个值。
    • 如果值被借用,则不起作用。
    • 在空单元格上不起作用。
  • computetry_compute
    • 调用一个Fn以条件性地计算一个新值作为替换。
    • 如果值被借用,则不起作用。
  • compute_if_presenttry_compute_if_present
    • 调用一个Fn以条件性地计算一个新值作为替换。
    • 如果值被借用,则不起作用。
    • 在空单元格上什么也不做。
  • compute_if_absent
    • 调用一个Fn来计算一个新值。
    • 在空单元格或具有借用值的单元格上什么也不做。
  • swaptry_swap
    • 就像RefCell::swap一样
    • 将在两个单元格之间交换值。

访问

  • get_and_clonetry_get_and_clone
    • 直接返回单元格当前值的副本。
    • 如果值是可变借用,则不会工作。
    • 在空单元格上不起作用。
    • 仅在实现 Clone 特性的类型上可用。
  • if_present_mutif_presenttry_if_presenttry_if_present_mut
    • 如果单元格不为空,则通过值引用调用 Fn。
    • 空单元格上不执行任何操作。
    • 如果值被借用,则 mut 变体将不会工作。
    • 如果值被可变借用,则正常变体将不会工作。
  • mapmap_muttry_maptry_map_mut
    • 通过值引用调用 Fn 以执行类型转换。
    • Fn 的签名是 Fn(&T) -> XFn(&mut T) -> X
      • X 是转换的结果类型。
      • T 是单元格中的类型。
    • 整个方法签名是 Option<X>Result<Option<X>, RcOCellError>
    • 在空单元格上不起作用。
    • 如果值被借用,则 mut 变体将不会工作。
    • 如果值被可变借用,则正常变体将不会工作。

转换

  • T 可以通过 into 转换为 RcOCell<T>
  • RcOCell<Vec<T>> 可以通过 try_into 转换为 Vec<T>
  • RcOCell<T> 可以通过 into 转换为 Rc<RefCell<Option<T>>>
  • Rc<RefCell<Option<T>>> 可以通过 into 转换为 RcOCell<T>
  • RcOCell<T> 可以通过 into 转换为 WeakRcOCell<T>
    • 还有一个专门的 downgrade 方法,就像 Rc::downgrade
  • WeakRcOCell<T> 可以通过 try_into 转换为 RcOCell<T>
    • 还有一个专门的 upgrade 方法,就像 Rc::upgrade
  • RcOCell<T>可以通过try_into转换为Option<T>
  • RcOCell<T>可以通过into转换为Result<Option<T>, RcOCellError>
  • 普通RefCell借用方法的'error'类型可以通过into?运算符转换为RcOCellError

构造函数

  • from_valuefrom
    • 创建一个带有值的新的cell,其中一个来自From<T>特质
  • from_option
    • 接收一个Option作为参数,并创建一个带有或没有值的cell。
  • new
    • 创建一个空cell。

杂项

  • downgradeupgrade
    • 弱引用和普通引用cell之间的转换
  • clone
    • 就像Rc::clone一样增加引用计数。

更大的例子

pub fn main() {
    let cell : RcOCell<u8> = RcOCell::from_value(1u8); //RcOCell::new() creates a empty cell.

    //Remove the value from the cell
    let old_value : Option<u8> = cell.clear(); //old value would be 1u8.
    let borrow_result : Result<u8, RcOCellError> = cell.try_borrow();
    if borrow_result.is_err() {
        //Would be error because cell is empty.
        //If you want to handle the RcOCellError error, it's an enum. 
        //Can be handled like this:
        match borrow_result.unwrap_err() {
            RcOCellError::NoValue => {println!("No value present")},
            RcOCellError::BorrowError(_) => {}, //Won't happen in this case
            RcOCellError::Dropped => {}, //Won't happen in this case
        }
    }

    //Now cell has value 2. old_value is None.
    let old_value : u8 = cell.set(2u8);
    let borrowed : Ref<u8> = cell.borrow();
    //set would panic, because the value is still borrowed, try_set will fail with RcOCellError::BorrowError
    let try_set_result : Result<u8, RcOCellError> = cell.try_set(4u8);
    drop(borrowed);
    //Now it will work!
    let try_set_result : Result<u8, RcOCellError> = cell.try_set(4u8);
    //2u8 is the old value, 4u8 is now in the cell
    let old_value : u8 = try_set_result.unwrap();
    let current_value : u8 = cell.get_and_clone(); //Only works for all T that implement Clone trait, in this case 4u8
    let current_value : u8 = cell.get_and_clear(); //Cell is empty again after this call. current_value 4u8
    //Another call to get_and_clear would panic as cell is empty.
    let get_result : Result<u8, RcOCellError> = cell.try_get_and_clear();
    //Result is once again RcOCellError::NoValue Error
}

无运行时依赖