1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use core::marker::PhantomData;

/// [`Copy`] version of [`Compact`](crate::Compact).
///
/// # Examples
///
/// ```
/// use enum_ptr::{CompactCopy, EnumPtr};
///
/// #[derive(EnumPtr, Debug, Clone, Copy, PartialEq, Eq)]
/// #[enum_ptr(copy)] // required
/// #[repr(C, usize)]
/// enum Foo<'a, 'b> {
///     A(&'a i32),
///     B(&'b u32),
/// }
///
/// let foo: CompactCopy<_> = Foo::A(&1).into();
/// assert_eq!(foo.extract(), Foo::A(&1));
/// assert_ne!(foo.extract(), Foo::B(&2));
/// ```
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct CompactCopy<T>
where
    T: From<CompactCopy<T>> + Copy,
    CompactCopy<T>: From<T>,
{
    data: *const u8,
    marker: PhantomData<T>,
}

impl<T> CompactCopy<T>
where
    T: From<CompactCopy<T>> + Copy,
    CompactCopy<T>: From<T>,
{
    /// Returns the underlying raw data.
    #[inline]
    pub fn as_raw_data(&self) -> *const u8 {
        self.data
    }

    /// Alias of `T::from(self)`.
    #[inline]
    pub fn extract(self) -> T {
        self.into()
    }
}

impl<T> PartialEq for CompactCopy<T>
where
    T: From<CompactCopy<T>> + Copy + PartialEq,
    CompactCopy<T>: From<T>,
{
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.extract().eq(&other.extract())
    }
}

impl<T> Eq for CompactCopy<T>
where
    T: From<CompactCopy<T>> + Copy + Eq,
    CompactCopy<T>: From<T>,
{
}

impl<T> PartialOrd for CompactCopy<T>
where
    T: From<CompactCopy<T>> + Copy + PartialOrd,
    CompactCopy<T>: From<T>,
{
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
        self.extract().partial_cmp(&other.extract())
    }
}

impl<T> Ord for CompactCopy<T>
where
    T: From<CompactCopy<T>> + Copy + Ord,
    CompactCopy<T>: From<T>,
{
    #[inline]
    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
        self.extract().cmp(&other.extract())
    }
}

impl<T> core::fmt::Debug for CompactCopy<T>
where
    T: From<CompactCopy<T>> + Copy + core::fmt::Debug,
    CompactCopy<T>: From<T>,
{
    #[inline]
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        self.extract().fmt(f)
    }
}

impl<T> Default for CompactCopy<T>
where
    T: From<CompactCopy<T>> + Copy + Default,
    CompactCopy<T>: From<T>,
{
    fn default() -> Self {
        T::default().into()
    }
}

impl<T> core::hash::Hash for CompactCopy<T>
where
    T: From<CompactCopy<T>> + Copy + core::hash::Hash,
    CompactCopy<T>: From<T>,
{
    #[inline]
    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
        self.extract().hash(state)
    }
}

unsafe impl<T> Send for CompactCopy<T>
where
    T: From<CompactCopy<T>> + Copy + Send,
    CompactCopy<T>: From<T>,
{
}

unsafe impl<T> Sync for CompactCopy<T>
where
    T: From<CompactCopy<T>> + Copy + Sync,
    CompactCopy<T>: From<T>,
{
}