Skip to content
Open
Changes from all 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
84 changes: 42 additions & 42 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![deny(missing_docs)]
#![cfg_attr(feature = "oibit", feature(optin_builtin_traits))]
#![cfg_attr(feature = "oibit", feature(auto_traits, negative_impls))]

//! A safe approach to using `#[repr(packed)]` data.
//!
Expand All @@ -9,11 +9,47 @@ use std::mem::{transmute, uninitialized, forget, align_of, size_of};
use std::ptr::write;
use std::marker::PhantomData;

/// A marker trait indicating that a type has an alignment of `1`.
///
/// In general, only applies to `()`, `bool`, `i8`, `u8`, and any types that
/// contain only members of these types.
pub unsafe trait Unaligned { }
macro_rules! define_marker_trait_unaligned {
([$($auto:ident)?] $($impl:item)*) => {
Copy link
Copy Markdown
Author

@fmease fmease Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm using the Kleene ? out of convenience. However, that sets the minimum supported Rust version (MSRV) to 1.37 (2019). I could replace it with Kleene * to potentially lower the MSRV if you'd like me to. I haven't investigated the MSRV of the master branch.

/// A marker trait indicating that a type has an alignment of `1`.
///
/// In general, only applies to `()`, `bool`, `i8`, `u8`, and any types that
/// contain only members of these types.
pub unsafe $($auto)? trait Unaligned { }

$($impl)*
}
}

#[cfg(not(feature = "oibit"))]
define_marker_trait_unaligned! { []
unsafe impl Unaligned for () { }
unsafe impl Unaligned for i8 { }
unsafe impl Unaligned for u8 { }
unsafe impl Unaligned for bool { }
}

#[cfg(feature = "oibit")]
define_marker_trait_unaligned! { [auto]
// All primitives except the packed ones listed above
impl !Unaligned for char { }
impl !Unaligned for f32 { }
impl !Unaligned for f64 { }
impl !Unaligned for i16 { }
impl !Unaligned for u16 { }
impl !Unaligned for i32 { }
impl !Unaligned for u32 { }
impl !Unaligned for i64 { }
impl !Unaligned for u64 { }
impl !Unaligned for isize { }
impl !Unaligned for usize { }
impl<T> !Unaligned for *const T { }
impl<T> !Unaligned for *mut T { }
impl<'a, T> !Unaligned for &'a T { }
impl<'a, T> !Unaligned for &'a mut T { }
}

unsafe impl<T> Unaligned for PhantomData<T> { }

/// A type alias that represents the unaligned type of `T`.
pub type Un<T> = <T as Aligned>::Unaligned;
Expand Down Expand Up @@ -134,42 +170,6 @@ pub unsafe trait Packed: Unaligned {
fn __assert_unaligned() { }
}

#[cfg(feature = "oibit")]
mod impls {
use super::Unaligned;

unsafe impl Unaligned for .. { }

// All primitives except the packed ones listed below
impl !Unaligned for char { }
impl !Unaligned for f32 { }
impl !Unaligned for f64 { }
impl !Unaligned for i16 { }
impl !Unaligned for u16 { }
impl !Unaligned for i32 { }
impl !Unaligned for u32 { }
impl !Unaligned for i64 { }
impl !Unaligned for u64 { }
impl !Unaligned for isize { }
impl !Unaligned for usize { }
impl<T> !Unaligned for *const T { }
impl<T> !Unaligned for *mut T { }
impl<'a, T> !Unaligned for &'a T { }
impl<'a, T> !Unaligned for &'a mut T { }
}

#[cfg(not(feature = "oibit"))]
mod impls {
use super::Unaligned;

unsafe impl Unaligned for () { }
unsafe impl Unaligned for i8 { }
unsafe impl Unaligned for u8 { }
unsafe impl Unaligned for bool { }
}

unsafe impl<T> Unaligned for PhantomData<T> { }

macro_rules! aligned_assert {
($t:ident) => {
unsafe fn __assert_unaligned() {
Expand Down