Skip to main content

osom_lib_reprc/
traits.rs

1//! Holds the `#[repr(C)]` related traits and implementations, in particular the [`ReprC`] trait.
2
3use core::{
4    cell::{RefCell, UnsafeCell},
5    convert::Infallible,
6    marker::PhantomData,
7    mem::{ManuallyDrop, MaybeUninit},
8    ptr::NonNull,
9    sync::atomic::{
10        AtomicBool, AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize, AtomicPtr, AtomicU8, AtomicU16, AtomicU32,
11        AtomicU64, AtomicUsize,
12    },
13};
14
15/// Ensures that the type implementing it is `#[repr(C)]`.
16/// This cannot be guaranteed in general, and therefore we
17/// rely on macros to achieve that. This is a marker trait.
18///
19/// # Safety
20///
21/// This is an inherently unsafe trait. Any type implementing it
22/// has to have `#[repr(C)]` set recursively.
23pub unsafe trait ReprC {
24    /// This field is used for const checks only.
25    const CHECK: ();
26}
27
28macro_rules! impl_reprc {
29    ( $t: ty ) => {
30        unsafe impl ReprC for $t {
31            const CHECK: () = ();
32        }
33    };
34
35    ( $t: ty, $($ta: ty),* ) => {
36        impl_reprc!($t);
37        impl_reprc!($($ta),*);
38    }
39}
40
41macro_rules! impl_generic_reprc {
42    ( $t: ty ) => {
43        unsafe impl<T: ReprC> ReprC for $t {
44            const CHECK: () = {
45                let () = T::CHECK;
46            };
47        }
48    };
49
50    ( $t: ty, $($ta: ty),* ) => {
51        impl_generic_reprc!($t);
52        impl_generic_reprc!($($ta),*);
53    }
54}
55
56impl_reprc!(
57    i8,
58    u8,
59    i16,
60    u16,
61    i32,
62    u32,
63    i64,
64    u64,
65    i128,
66    u128,
67    f32,
68    f64,
69    (),
70    bool,
71    isize,
72    usize,
73    AtomicBool,
74    AtomicI8,
75    AtomicU8,
76    AtomicI16,
77    AtomicU16,
78    AtomicI32,
79    AtomicU32,
80    AtomicI64,
81    AtomicU64,
82    AtomicIsize,
83    AtomicUsize,
84    Infallible
85);
86
87impl_generic_reprc!(
88    AtomicPtr<T>,
89    *const T,
90    *mut T,
91    &T,
92    &mut T,
93    NonNull<T>,
94    ManuallyDrop<T>,
95    MaybeUninit<T>
96);
97
98unsafe impl<T: ReprC, const N: usize> ReprC for [T; N] {
99    const CHECK: () = {
100        let () = T::CHECK;
101    };
102}
103
104// PhantomData is a special case, that works with any T, since its size is 0
105// anyway.
106unsafe impl<T> ReprC for PhantomData<T> {
107    const CHECK: () = {
108        assert!(size_of::<PhantomData<T>>() == 0);
109    };
110}
111
112unsafe impl<T: ReprC> ReprC for UnsafeCell<T> {
113    const CHECK: () = {
114        let () = T::CHECK;
115    };
116}
117
118unsafe impl<T: ReprC> ReprC for RefCell<T> {
119    const CHECK: () = {
120        let () = T::CHECK;
121    };
122}