#interior-mutability #cell #unsafecell

no-std 近安全单元

更便捷的 'UnsafeCell' 包装/替代品

6 个版本

0.1.5 2022 年 5 月 4 日
0.1.4 2021 年 9 月 21 日

#13 in #interior-mutability

MIT/Apache

14KB
251

build test codecov docs crates.io

NearSafeCell,一个更便捷的 UnsafeCell 包装/替代品。

原因

标准的 UnsafeCell API 在某些情况下并不是很好用。

  • &T 获取 &UnsafeCell<T> 没有使用简单且始终安全的 unsafe{ &*cell.get() };
  • UnsafeCell::get 返回一个 &mut T,无论如何都需要不安全地解引用和重新引用来使用,所以为什么不直接返回一个引用并使函数本身不安全呢?
  • UnsafeCell::get 的命名与自身和标准库的其他部分混淆且不一致 - 它应该真正地称为 UnsafeCell::get_mut_ptr
  • 如果您确实只需要一个指针(例如作为映射键),您可以直接使用 &self as *const T。根本不需要 UnsafeCell

使用方法

use near_safe_cell::NearSafeCell;

// Implements 'Default'
let mut cell: NearSafeCell<usize> = NearSafeCell::default();
cell = NearSafeCell::new(24);

// Implements all Formatting traits
assert_eq!(format!("{:b}", cell), "11000");
assert_eq!(format!("{:?}", cell), "NearSafeCell(24)");

// Implements 'AsRef', 'AsMut', 'Deref' and 'DerefMut'
assert_eq!(cell.as_ref(), &24);
assert_eq!(cell.as_mut(), &mut 24);
assert_eq!(&*cell, &24);
assert_eq!(&mut *cell, &mut 24);

// You can still get pointers.
let const_ptr: *const usize = cell.get_ptr(); // &self
let mut_ptr: *mut usize = cell.get_mut_ptr(); // &self

// Safety: 'interiorly_mutable' is dropped before retrieving 'shared'.
let interiorly_mutable: &mut usize = unsafe{ cell.get_mut_unsafe() }; // &self
assert_eq!(interiorly_mutable, &mut 24);
*interiorly_mutable = 42;
drop(interiorly_mutable);

// Multiple shared references.
let shared: &usize = cell.get(); // &self
let shared2: &usize = cell.get(); // &self
assert_eq!(shared, &42);
assert_eq!(shared, shared2);

// One mutable reference.
let mutable: &mut usize = cell.get_mut(); // &mut self
assert_eq!(mutable, &mut 42);
*mutable = 242;

// Consuming the cell to get the value.
let value: usize = cell.unwrap(); // self
assert_eq!(value, 242);

无运行时依赖