2 个版本

0.1.0 2024 年 3 月 23 日
0.1.0-beta.02024 年 3 月 21 日

数据结构 中排名第 465

MIT 许可证

29KB
446

pas-rs

pas (\pa\), 法语中意为 "步长",是一个用于切片的包,尤其适用于步长数据。

pas 允许您

  • 获取具有自定义步长的切片
  • 仅切片结构体的一部分

⚠️ 此包依赖于不同数据类型之间的转换 ⚠️

  • 此操作依赖于字节序
  • 未提供从/到大端编码/解码的机制

示例

使用类型推断

使用 slice_attr!struct 中切片并自动推断类型

use pas::{slice, slice_attr};

#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
struct Vertex {
    pub position: [f32; 3],
    pub uv: [f32; 2],
}

fn main() {
    let vertices = [
        Vertex {position: [1.0, 0.5, 1.0], uv: [1.0, 1.0]},
        Vertex {position: [1.0, 1.0, 0.5], uv: [0.0, 1.0]},
    ];

    // Start slice at first vertex, pointing at `position`.
    let positions = slice_attr!(vertices, [0].position);
    println!("{:?}", positions); // [[1.0, 0.5, 1.0], [1.0, 1.0, 0.5]]

    // Start slice at second vertex, pointing at `uv`.
    let uvs = slice_attr!(vertices, [1].uv);
    println!("{:?}", uvs); // [[0.0, 1.0]]
}

不使用类型推断

在结构体属性上进行切片可能很有用,但类型较小

let x_positions: Slice<f32> = slice!(vertices, [0].position[0]);
println!("{:?}", x_positions); // [1.0, 1.0]

let y_positions: Slice<f32> = slice!(vertices, [0].position[1]);
println!("{:?}", y_positions); // [0.5, 1.0]

let z_positions: Slice<f32> = slice!(vertices, [0].position[2]);
println!("{:?}", z_positions); // [1.0, 0.5]

切片和切片可变

当切片数组的类型信息仅在运行时已知时,您可以使用 Slice/SliceMut

let uv_byte_offset = std::mem::size_of::<Vertex>() + std::mem::size_of::<[f32; 3]>();

// Slice starting at the byte offset `32`, with a stride of 1 element.
let uvs: Slice<[f32; 3]> = Slice::new(&vertices, uv_byte_offset);
println!("{:?}", uvs); // [[0.0, 1.0]]

自定义步长

可以使用自定义步长,以元素计数的方式

use pas::{slice_attr, Slice};

let data: [u32; 5] = [0, 1, 2, 3, 4];

// Using the macro, the stride appears first
let slice = slice_attr!(2, data, [0]);
println!("{:?}", slice); // [0, 2, 4]

// Specified as the last argument when using `Slice`/`SliceMut`
let slice: Slice<u32> = Slice::strided(&data, 0, 3);
println!("{:?}", slice); // [0, 3]

步长必须始终至少与属性的尺寸相同。此示例将引发恐慌

use pas::{slice_attr, Slice};

let data: [u32; 5] = [0, 1, 2, 3, 4];
// Default stride is `std::mem::size_of::<u32>()` here, attribute
// size is `std::mem::size_of::<[u32; 3]>()`.
let _: Slice<[u32; 3]> = Slice::new(&data, 0);

安全性

虽然此包使用了 unsafetransmute,但它(主要是)安全使用,并带有运行时检查,可防止您遇到未定义的行为

  • 确保读取对齐
  • 检查读取大小与步长的比较

此包要求您的类型实现来自 bytemuck cratePod trait,通过对齐规则和非法位模式提高安全性。

依赖项

~135KB