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}