33个版本 (稳定)
1.0.23 | 2024年5月7日 |
---|---|
1.0.22 | 2024年1月2日 |
1.0.21 | 2023年12月13日 |
1.0.20 | 2023年8月17日 |
0.2.0 | 2017年10月28日 |
#28 in #repr
807,582 每月下载量
在 1,788 个crate中使用(通过 ref-cast)
19KB
389 行代码(不含注释)
RefCast
安全地将 &T
转换为 &U
,其中结构体 U
包含一个类型为 T
的字段。
[dependencies]
ref-cast = "1.0"
基本示例
use ref_cast::RefCast;
#[derive(RefCast)]
#[repr(transparent)]
struct U(String);
fn main() {
let s = String::new();
// Safely cast from `&String` to `&U`.
let u = U::ref_cast(&s);
}
请注意,为了使转换有效,需要 #[repr(transparent)]
。如果不存在,派生宏将拒绝编译。
真实示例
假设我们有一个多维数组,由于性能原因,它以行主序的方式表示在扁平缓冲区中,但我们需要公开一个以列主序工作的索引操作,因为在我们的应用程序上下文中这更直观。
const MAP_WIDTH: usize = 4;
struct Tile(u8);
struct TileMap {
storage: Vec<Tile>,
}
// `tilemap[x][y]` should give us `tilemap.storage[y * MAP_WIDTH + x]`.
Rust 中 Index
特性的签名是这样的,输出被强制从被索引的类型借用。所以以下代码将无法工作。
struct Column<'a> {
tilemap: &'a TileMap,
x: usize,
}
// Does not work! The output of Index must be a reference that is
// borrowed from self. Here the type Column is not a reference.
impl Index<usize> for TileMap {
fn index(&self, x: usize) -> Column {
assert!(x < MAP_WIDTH);
Column { tilemap: self, x }
}
}
impl<'a> Index<usize> for Column<'a> {
fn index(&self, y: usize) -> &Tile {
&self.tilemap.storage[y * MAP_WIDTH + self.x]
}
}
以下是一个使用 RefCast
的工作方法。
#[derive(RefCast)]
#[repr(transparent)]
struct Strided([Tile]);
// Implement `tilemap[x][y]` as `tilemap[x..][y * MAP_WIDTH]`.
impl Index<usize> for TileMap {
type Output = Strided;
fn index(&self, x: usize) -> &Self::Output {
assert!(x < MAP_WIDTH);
Strided::ref_cast(&self.storage[x..])
}
}
impl Index<usize> for Strided {
type Output = Tile;
fn index(&self, y: usize) -> &Self::Output {
&self.0[y * MAP_WIDTH]
}
}
许可证
根据您的选择,受Apache许可证版本2.0 或 MIT许可证 的许可。除非您明确说明,否则任何有意提交以包含在此crate中并由您定义的贡献,根据Apache-2.0许可证,将按照上述双重许可,而不附加任何其他条款或条件。
依赖关系
~260–700KB
~17K SLoC