ostd_pod/
lib.rs

1//! This crate defines a marker trait for plain old data (POD).
2
3#![no_std]
4
5use core::mem::MaybeUninit;
6
7/// A marker trait for plain old data (POD).
8///
9/// A POD type `T:Pod` supports converting to and from arbitrary
10/// `mem::size_of::<T>()` bytes _safely_.
11/// For example, simple primitive types like `u8` and `i16`
12/// are POD types. But perhaps surprisingly, `bool` is not POD
13/// because Rust compiler makes implicit assumption that
14/// a byte of `bool` has a value of either `0` or `1`.
15/// Interpreting a byte of value `3` has a `bool` value has
16/// undefined behavior.
17///
18/// # Safety
19///
20/// Marking a non-POD type as POD may cause undefined behaviors.
21pub unsafe trait Pod: Copy + Sized {
22    /// Creates a new instance of Pod type that is filled with zeroes.
23    fn new_zeroed() -> Self {
24        // SAFETY. An all-zero value of `T: Pod` is always valid.
25        unsafe { core::mem::zeroed() }
26    }
27
28    /// Creates a new instance of Pod type with uninitialized content.
29    fn new_uninit() -> Self {
30        // SAFETY. A value of `T: Pod` can have arbitrary bits.
31        #[allow(clippy::uninit_assumed_init)]
32        unsafe {
33            MaybeUninit::uninit().assume_init()
34        }
35    }
36
37    /// Creates a new instance from the given bytes.
38    fn from_bytes(bytes: &[u8]) -> Self {
39        let mut new_self = Self::new_uninit();
40        let copy_len = new_self.as_bytes().len();
41        new_self.as_bytes_mut().copy_from_slice(&bytes[..copy_len]);
42        new_self
43    }
44
45    /// As a slice of bytes.
46    fn as_bytes(&self) -> &[u8] {
47        let ptr = self as *const Self as *const u8;
48        let len = core::mem::size_of::<Self>();
49        unsafe { core::slice::from_raw_parts(ptr, len) }
50    }
51
52    /// As a mutable slice of bytes.
53    fn as_bytes_mut(&mut self) -> &mut [u8] {
54        let ptr = self as *mut Self as *mut u8;
55        let len = core::mem::size_of::<Self>();
56        unsafe { core::slice::from_raw_parts_mut(ptr, len) }
57    }
58}
59
60macro_rules! impl_pod_for {
61    ($($pod_ty:ty),*) => {
62        $(unsafe impl Pod for $pod_ty {})*
63    };
64}
65// impl Pod for primitive types
66impl_pod_for!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, isize, usize);
67// impl Pod for array
68unsafe impl<T: Pod, const N: usize> Pod for [T; N] {}
69
70#[cfg(feature = "derive")]
71pub use ostd_pod_derive::*;