zeroable/
assert_zeroable.rs

1//! Contains both a trait and a type to contrain some type with `Zeroable`.
2
3use crate::Zeroable;
4
5use bytemuck::Pod;
6
7use core::{
8    cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd},
9    fmt::{self, Debug},
10    hash::{Hash, Hasher},
11    marker::PhantomData,
12    mem,
13};
14
15/// A marker type representing that `T` is `Zeroable`.
16///
17/// This type is zero-sized.
18#[repr(C)]
19pub struct AssertZeroable<T: ?Sized>(PhantomData<T>);
20
21const _ZERO_SIZED: [(); 1 - core::mem::size_of::<AssertZeroable<()>>()] = [()];
22
23impl<T> AssertZeroable<T>
24where
25    T: Zeroable + ?Sized,
26{
27    /// Constructs a `AssertZeroable<T>`
28    pub const NEW: Self = AssertZeroable(PhantomData);
29}
30
31impl<T> AssertZeroable<T> {
32    /// Gets a zeroed `T`.
33    ///
34    /// This is safe to call,
35    /// since constructing a `AssertZeroable<T>` requires that `T` is `Zeroable`.
36    #[inline(always)]
37    pub fn zeroed(self) -> T {
38        unsafe { mem::zeroed() }
39    }
40}
41
42unsafe impl<T> Zeroable for AssertZeroable<T> where T: Zeroable {}
43
44unsafe impl<T> Pod for AssertZeroable<T> where T: Pod {}
45
46impl<T: ?Sized> Copy for AssertZeroable<T> {}
47
48impl<T: ?Sized> Clone for AssertZeroable<T> {
49    fn clone(&self) -> Self {
50        *self
51    }
52}
53
54impl<T: ?Sized> PartialEq for AssertZeroable<T> {
55    #[inline]
56    fn eq(&self, _other: &Self) -> bool {
57        true
58    }
59}
60
61impl<T: ?Sized> Eq for AssertZeroable<T> {}
62
63impl<T: ?Sized> PartialOrd for AssertZeroable<T> {
64    #[inline]
65    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
66        Some(self.cmp(other))
67    }
68}
69
70impl<T: ?Sized> Ord for AssertZeroable<T> {
71    #[inline]
72    fn cmp(&self, _other: &Self) -> Ordering {
73        Ordering::Equal
74    }
75}
76
77impl<T: ?Sized> Hash for AssertZeroable<T> {
78    fn hash<H>(&self, state: &mut H)
79    where
80        H: Hasher,
81    {
82        ().hash(state)
83    }
84}
85
86impl<T: ?Sized> Debug for AssertZeroable<T> {
87    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88        let mut ds = f.debug_struct("AssertZeroable");
89
90        #[cfg(feature = "print_type")]
91        let ds = ds.field("type", &core::any::type_name::<T>());
92
93        ds.finish()
94    }
95}
96
97////////////////////////////////////////////////////////////////////////////////
98
99/// Constructs an `AssertZeroable<Self>`.
100/// Declared to improve the error message when a field does not implement `Zeroable`.
101pub trait GetAssertZeroable: Zeroable {
102    /// Gets an `AssertZeroable<Self>`,
103    /// a marker type representing that `T` is `Zeroable`
104    const GET: AssertZeroable<Self> = AssertZeroable::NEW;
105}
106
107impl<This: ?Sized + Zeroable> GetAssertZeroable for This {}