Skip to main content

compio_io/ancillary/
bytemuck_ext.rs

1//! Extension module for automatic [`AncillaryData`] implementation via
2//! bytemuck.
3//!
4//! See [`BitwiseAncillaryData`] for details.
5
6use std::mem::MaybeUninit;
7
8pub use bytemuck::{Pod, Zeroable};
9
10use super::{AncillaryData, CodecError, copy_from_bytes, copy_to_bytes};
11
12/// Marker trait to enable automatic `AncillaryData` implementation via
13/// bytemuck.
14///
15/// Types that implement this trait (which requires [`bytemuck::Pod`]) will
16/// automatically implement [`AncillaryData`] using a simple byte-wise
17/// encoding/decoding.
18///
19/// # Example
20///
21/// ```
22/// use compio_io::ancillary::bytemuck_ext;
23///
24/// #[derive(Clone, Copy)]
25/// #[repr(C)]
26/// struct MyType {
27///     value: u32,
28/// }
29///
30/// unsafe impl bytemuck_ext::Zeroable for MyType {}
31/// unsafe impl bytemuck_ext::Pod for MyType {}
32/// impl bytemuck_ext::BitwiseAncillaryData for MyType {}
33///
34/// // Now MyType automatically implements AncillaryData
35/// ```
36pub trait BitwiseAncillaryData: Pod {}
37
38impl<T: BitwiseAncillaryData> AncillaryData for T {
39    fn encode(&self, buffer: &mut [MaybeUninit<u8>]) -> Result<(), CodecError> {
40        unsafe { copy_to_bytes(self, buffer) }
41    }
42
43    fn decode(buffer: &[u8]) -> Result<Self, CodecError> {
44        unsafe { copy_from_bytes(buffer) }
45    }
46}
47
48macro_rules! impl_bytemuck_marker {
49    ($($t:ty),* $(,)?) => {
50        $(
51            impl BitwiseAncillaryData for $t {}
52        )*
53    };
54}
55
56impl_bytemuck_marker!(
57    (),
58    u8,
59    u16,
60    u32,
61    u64,
62    u128,
63    usize,
64    i8,
65    i16,
66    i32,
67    i64,
68    i128,
69    isize,
70    f32,
71    f64,
72);
73
74impl<T: BitwiseAncillaryData, const N: usize> BitwiseAncillaryData for [T; N] {}