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] {}