pas/macros.rs
1/// Make the slice point to the referenced element
2///
3/// The slice generic type will be resolved to the type of
4/// the attribute passed as the second macro argument.
5///
6/// ## Example
7///
8/// ```rust
9/// use pas::slice_attr;
10///
11/// #[repr(C)]
12/// #[derive(Clone, Copy, Default, bytemuck::Pod, bytemuck::Zeroable)]
13/// struct Vertex {
14/// position: [f32; 3],
15/// uv: [f32; 2],
16/// }
17///
18/// let vertices = [
19/// Vertex {position: [1.0, 0.5, 1.0], uv: [1.0, 1.0]},
20/// Vertex {position: [1.0, 1.0, 0.5], uv: [0.0, 1.0]},
21/// ];
22/// let positions = slice_attr!(vertices, [0].position); // 2 positions
23/// let uvs = slice_attr!(vertices, [1].uv); // 1 uv
24/// ```
25///
26/// The stride, in **element count**, can be passed as a first argument:
27///
28/// ```rust
29/// use pas::slice_attr;
30///
31/// let data = [0, 1, 2, 3, 4, 5, 6];
32/// let slice = slice_attr!(2, data, [0]);
33/// println!("{:?}", slice)
34/// ````
35#[macro_export]
36macro_rules! slice_attr {
37 ($stride:expr, $data:expr, $( $rest:tt )*) => {
38 {
39 use pas::SliceBuilder;
40
41 let slice = $data.as_slice();
42 let r = &(slice$($rest)*);
43 SliceBuilder::new(r, $stride).build(slice)
44 }
45 };
46 ($data:expr, $( $rest:tt )*) => {
47 slice_attr!(1, $data, $($rest)*)
48 };
49}
50
51/// Similar to [`slice_attr!`].
52///
53/// At the opposite of [`slice_attr`], this macro doesn't infer the slice generic.
54/// This allows to get a view on a type that has a smaller size than the target attribute.
55///
56/// ## Example
57///
58/// ```rust
59/// use pas::{slice, Slice};
60///
61/// #[repr(C)]
62/// #[derive(Clone, Copy, Default, bytemuck::Pod, bytemuck::Zeroable)]
63/// struct Vertex {
64/// position: [f32; 3],
65/// uv: [f32; 2],
66/// }
67///
68/// let vertices = [
69/// Vertex {position: [1.0, 0.5, 1.0], uv: [1.0, 1.0]},
70/// Vertex {position: [1.0, 1.0, 0.5], uv: [0.0, 1.0]},
71/// ];
72/// // Only slice the x-axis positions
73/// let x_positions: Slice<f32> = slice!(vertices, [0].position[0]);
74/// ```
75#[macro_export]
76macro_rules! slice {
77 ($stride:expr, $data:expr, $( $rest:tt )*) => {
78 {
79 use pas::{Slice, get_byte_offset};
80
81 let slice = $data.as_slice();
82 let r = &(slice$($rest)*) as *const _ as *const u8;
83 let byte_offset = get_byte_offset(slice, r);
84 Slice::strided(slice, byte_offset, $stride)
85 }
86 };
87 ($data:expr, $( $rest:tt )*) => {
88 slice!(1, $data, $($rest)*)
89 };
90}
91
92/// Similar to [`slice!`], but for [`crate::SliceMut`].
93#[macro_export]
94macro_rules! slice_mut {
95 ($stride:expr, $data:expr, $( $rest:tt )*) => {
96 {
97 use pas::{get_byte_offset, SliceMut};
98
99 let slice = $data.as_mut_slice();
100 let r = &(slice$($rest)*) as *const _ as *const u8;
101 let byte_offset = get_byte_offset(slice, r);
102 SliceMut::strided(slice, byte_offset, $stride)
103 }
104 };
105 ($data:expr, $( $rest:tt )*) => {
106 slice_mut!(1, $data, $($rest)*)
107 };
108}
109
110/// Similar to [`slice_attr!`], but for [`crate::SliceMut`].
111#[macro_export]
112macro_rules! slice_attr_mut {
113 ($stride:expr, $data:expr, $( $rest:tt )*) => {
114 {
115 use pas::SliceBuilder;
116
117 let slice = $data.as_mut_slice();
118 let r = &(slice$($rest)*);
119 SliceBuilder::new(r, $stride).build_mut(slice)
120 }
121 };
122 ($data:expr, $( $rest:tt )*) => {
123 slice_attr_mut!(1, $data, $($rest)*)
124 };
125}