cranelift_entity/
packed_option.rs1use core::fmt;
11use core::mem;
12
13#[cfg(feature = "enable-serde")]
14use serde_derive::{Deserialize, Serialize};
15
16pub trait ReservedValue {
18 fn reserved_value() -> Self;
20 fn is_reserved_value(&self) -> bool;
22}
23
24#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
29#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
30#[repr(transparent)]
31pub struct PackedOption<T: ReservedValue>(T);
32
33impl<T: ReservedValue> PackedOption<T> {
34 pub fn is_none(&self) -> bool {
36 self.0.is_reserved_value()
37 }
38
39 pub fn is_some(&self) -> bool {
41 !self.0.is_reserved_value()
42 }
43
44 pub fn expand(self) -> Option<T> {
46 if self.is_none() {
47 None
48 } else {
49 Some(self.0)
50 }
51 }
52
53 pub fn map<U, F>(self, f: F) -> Option<U>
55 where
56 F: FnOnce(T) -> U,
57 {
58 self.expand().map(f)
59 }
60
61 #[track_caller]
63 pub fn unwrap(self) -> T {
64 self.expand().unwrap()
65 }
66
67 #[track_caller]
69 pub fn expect(self, msg: &str) -> T {
70 self.expand().expect(msg)
71 }
72
73 pub fn take(&mut self) -> Option<T> {
75 mem::replace(self, None.into()).expand()
76 }
77}
78
79impl<T: ReservedValue> Default for PackedOption<T> {
80 fn default() -> Self {
82 Self(T::reserved_value())
83 }
84}
85
86impl<T: ReservedValue> From<T> for PackedOption<T> {
87 fn from(t: T) -> Self {
89 debug_assert!(
90 !t.is_reserved_value(),
91 "Can't make a PackedOption from the reserved value."
92 );
93 Self(t)
94 }
95}
96
97impl<T: ReservedValue> From<Option<T>> for PackedOption<T> {
98 fn from(opt: Option<T>) -> Self {
100 match opt {
101 None => Self::default(),
102 Some(t) => t.into(),
103 }
104 }
105}
106
107impl<T: ReservedValue> Into<Option<T>> for PackedOption<T> {
108 fn into(self) -> Option<T> {
109 self.expand()
110 }
111}
112
113impl<T> fmt::Debug for PackedOption<T>
114where
115 T: ReservedValue + fmt::Debug,
116{
117 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118 if self.is_none() {
119 write!(f, "None")
120 } else {
121 write!(f, "Some({:?})", self.0)
122 }
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129
130 #[derive(Debug, PartialEq, Eq)]
132 struct NoC(u32);
133
134 impl ReservedValue for NoC {
135 fn reserved_value() -> Self {
136 NoC(13)
137 }
138
139 fn is_reserved_value(&self) -> bool {
140 self.0 == 13
141 }
142 }
143
144 #[test]
145 fn moves() {
146 let x = NoC(3);
147 let somex: PackedOption<NoC> = x.into();
148 assert!(!somex.is_none());
149 assert_eq!(somex.expand(), Some(NoC(3)));
150
151 let none: PackedOption<NoC> = None.into();
152 assert!(none.is_none());
153 assert_eq!(none.expand(), None);
154 }
155
156 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
158 struct Ent(u32);
159
160 impl ReservedValue for Ent {
161 fn reserved_value() -> Self {
162 Ent(13)
163 }
164
165 fn is_reserved_value(&self) -> bool {
166 self.0 == 13
167 }
168 }
169
170 #[test]
171 fn copies() {
172 let x = Ent(2);
173 let some: PackedOption<Ent> = x.into();
174 assert_eq!(some.expand(), x.into());
175 assert_eq!(some, x.into());
176 }
177}