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