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