2 个版本
0.1.0 | 2024 年 3 月 23 日 |
---|---|
0.1.0-beta.0 | 2024 年 3 月 21 日 |
在 数据结构 中排名第 465
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);
安全性
虽然此包使用了 unsafe
和 transmute
,但它(主要是)安全使用,并带有运行时检查,可防止您遇到未定义的行为
- 确保读取对齐
- 检查读取大小与步长的比较
此包要求您的类型实现来自 bytemuck crate 的 Pod trait,通过对齐规则和非法位模式提高安全性。
依赖项
~135KB