1#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8#[repr(u64)]
9pub enum Optional<T> {
10 None,
11 Some(T),
12}
13
14impl<T> From<Option<T>> for Optional<T> {
15 #[inline]
16 fn from(opt: Option<T>) -> Self {
17 match opt {
18 Some(val) => Optional::Some(val),
19 None => Optional::None,
20 }
21 }
22}
23
24impl<T> From<Optional<T>> for Option<T> {
25 #[inline]
26 fn from(opt: Optional<T>) -> Self {
27 match opt {
28 Optional::Some(val) => Some(val),
29 Optional::None => None,
30 }
31 }
32}
33
34#[cfg(test)]
35mod tests {
36 use super::*;
37
38 #[test]
39 fn test_conversions() {
40 let std_opt = Some(123u64);
41 let stdbind_opt: Optional<u64> = std_opt.into();
42 assert_eq!(stdbind_opt, Optional::Some(123));
43
44 let back_to_std: Option<u64> = stdbind_opt.into();
45 assert_eq!(back_to_std, Some(123));
46
47 let none_std: Option<u64> = None;
48 let none_stdbind: Optional<u64> = none_std.into();
49 assert_eq!(none_stdbind, Optional::None);
50
51 let back_to_none: Option<u64> = none_stdbind.into();
52 assert_eq!(back_to_none, None);
53 }
54
55 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
56 #[repr(C)]
57 struct Point {
58 x: i32,
59 y: i32,
60 }
61
62 #[test]
63 fn test_layouts() {
64 assert_eq!(size_of::<Optional<u8>>(), 16);
65 assert_eq!(align_of::<Optional<u8>>(), 8);
66
67 assert_eq!(size_of::<Optional<u16>>(), 16);
68 assert_eq!(align_of::<Optional<u16>>(), 8);
69
70 assert_eq!(size_of::<Optional<u32>>(), 16);
71 assert_eq!(align_of::<Optional<u32>>(), 8);
72
73 assert_eq!(size_of::<Optional<u64>>(), 16);
74 assert_eq!(align_of::<Optional<u64>>(), 8);
75
76 assert_eq!(size_of::<Optional<Point>>(), 16);
77 assert_eq!(align_of::<Optional<Point>>(), 8);
78 }
79
80 #[test]
81 fn test_discriminants() {
82 let none: Optional<u32> = Optional::None;
83 assert_eq!(unsafe { *(core::ptr::addr_of!(none) as *const u64) }, 0);
84
85 let some: Optional<u32> = Optional::Some(0x12345678);
86 assert_eq!(unsafe { *(core::ptr::addr_of!(some) as *const u64) }, 1);
87 assert_eq!(
88 unsafe { *((core::ptr::addr_of!(some) as *const u8).add(8) as *const u32) },
89 0x12345678
90 );
91 }
92}