Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ compio-quic = { path = "./compio-quic", version = "0.7.0", default-features = fa
compio-ws = { path = "./compio-ws", version = "0.3.0", default-features = false }

bytes = "1.7.1"
bytemuck = "1.25.0"
cfg_aliases = "0.2.1"
cfg-if = "1.0.0"
criterion = "0.8.0"
Expand Down
6 changes: 5 additions & 1 deletion compio-io/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ cfg-if = { workspace = true, optional = true }
thiserror = { workspace = true, optional = true }
serde = { version = "1.0.219", optional = true }
serde_json = { version = "1.0.140", optional = true }
bytemuck = { workspace = true, optional = true }

[target.'cfg(unix)'.dependencies]
libc = { workspace = true, optional = true }
Expand All @@ -30,7 +31,6 @@ windows-sys = { workspace = true, optional = true, features = [
] }

[dev-dependencies]
aligned-array = "1.0.1"
tokio = { workspace = true, features = ["macros", "rt"] }
serde = { version = "1.0.219", features = ["derive"] }
futures-executor = "0.3.30"
Expand Down Expand Up @@ -58,3 +58,7 @@ required-features = ["compat"]
[[test]]
name = "framed"
required-features = ["codec-serde-json"]

[[test]]
name = "ancillary"
required-features = ["ancillary"]
88 changes: 88 additions & 0 deletions compio-io/src/ancillary/bytemuck_ext.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use std::mem::MaybeUninit;

use super::{AncillaryData, CodecError, copy_from_bytes, copy_to_bytes};

/// Marker trait to enable automatic `AncillaryData` implementation via
/// bytemuck.
///
/// Types that implement both [`bytemuck::NoUninit`] and this trait will
/// automatically implement [`AncillaryData`] using a simple byte-wise
/// encoding/decoding.
///
/// # Safety
Comment thread
fantix marked this conversation as resolved.
Outdated
///
/// This trait should only be implemented for types where a simple byte-wise
/// copy is a valid encoding/decoding strategy. The type must also implement
/// `bytemuck::NoUninit` to ensure it has no uninitialized bytes.
///
/// # Example
///
/// ```
/// use compio_io::ancillary::BytemuckMarker;
///
/// #[derive(Clone, Copy)]
/// #[repr(C)]
/// struct MyType {
/// value: u32,
/// }
///
/// unsafe impl bytemuck::NoUninit for MyType {}
/// impl BytemuckMarker for MyType {}
///
/// // Now MyType automatically implements AncillaryData
/// ```
pub trait BytemuckMarker {}
Comment thread
Berrysoft marked this conversation as resolved.
Outdated
Comment thread
fantix marked this conversation as resolved.
Outdated

impl<T> AncillaryData for T
where
T: bytemuck::NoUninit + BytemuckMarker,
{
fn encode(&self, buffer: &mut [MaybeUninit<u8>]) -> Result<(), CodecError> {
unsafe { copy_to_bytes(self, buffer) }
}

fn decode(buffer: &[u8]) -> Result<Self, CodecError> {
unsafe { copy_from_bytes(buffer) }
}
}

macro_rules! impl_bytemuck_marker {
($($t:ty),* $(,)?) => {
$(
impl BytemuckMarker for $t {}
)*
};
}

impl_bytemuck_marker!(
(),
bool,
char,
u8,
u16,
u32,
u64,
u128,
usize,
i8,
i16,
i32,
i64,
i128,
isize,
f32,
f64,
);

macro_rules! impl_bytemuck_marker_for_array {
($($N:expr),* $(,)?) => {
$(
impl<T> BytemuckMarker for [T; $N] where T: BytemuckMarker {}
)*
};
}

impl_bytemuck_marker_for_array!(
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32, 48, 64, 96, 128, 256, 512,
);
Loading
Loading