#cast #ref #repr #field #struct #safely #ref-cast

ref-cast-impl

为 ref_cast::RefCast 提供派生实现

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

Download history 188337/week @ 2024-04-22 173274/week @ 2024-04-29 163592/week @ 2024-05-06 191508/week @ 2024-05-13 186586/week @ 2024-05-20 213327/week @ 2024-05-27 214989/week @ 2024-06-03 187207/week @ 2024-06-10 192244/week @ 2024-06-17 213850/week @ 2024-06-24 194024/week @ 2024-07-01 189896/week @ 2024-07-08 207870/week @ 2024-07-15 215288/week @ 2024-07-22 201103/week @ 2024-07-29 174825/week @ 2024-08-05

807,582 每月下载量
1,788 个crate中使用(通过 ref-cast

MIT/Apache

19KB
389 行代码(不含注释)

RefCast

github crates.io docs.rs build status

安全地将 &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.0MIT许可证 的许可。
除非您明确说明,否则任何有意提交以包含在此crate中并由您定义的贡献,根据Apache-2.0许可证,将按照上述双重许可,而不附加任何其他条款或条件。

依赖关系

~260–700KB
~17K SLoC