#cast #safely #single #struct #field #suite #ref-cast

ref-cast-test-suite

ref-cast crate 的测试套件

1 个不稳定版本

0.0.0 2022 年 10 月 12 日

#47#safely

Download history 23/week @ 2024-03-11 14/week @ 2024-03-18 16/week @ 2024-03-25 42/week @ 2024-04-01 18/week @ 2024-04-08 23/week @ 2024-04-15 24/week @ 2024-04-22 13/week @ 2024-04-29 17/week @ 2024-05-06 23/week @ 2024-05-13 16/week @ 2024-05-20 42/week @ 2024-05-27 31/week @ 2024-06-03 38/week @ 2024-06-10 29/week @ 2024-06-17 35/week @ 2024-06-24

141 每月下载量
用于 ref-cast

MIT/Apache

1KB

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)] 属性。如果缺失, derive 宏将拒绝编译。

实际示例

假设我们有一个多维数组,为了性能原因,以行主序方式在平面缓冲区中表示,但因为我们希望在应用程序上下文中更直观,所以想提供一个以列主序工作的索引操作。

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 License, Version 2.0 或 MIT 许可证,任选其一。
除非您明确说明,否则根据 Apache-2.0 许可证定义,您有意提交的任何贡献,都将按照上述方式双重许可,不附加任何额外条款或条件。

无运行时依赖