cranelift_entity/
packed_option.rs1use core::{fmt, mem};
11use wasmtime_core::{alloc::TryClone, error::OutOfMemory};
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> TryClone for PackedOption<T>
34where
35 T: ReservedValue + TryClone,
36{
37 fn try_clone(&self) -> Result<Self, OutOfMemory> {
38 Ok(Self(self.0.try_clone()?))
39 }
40}
41
42impl<T: ReservedValue> PackedOption<T> {
43 pub const fn new(val: T) -> Self {
48 Self(val)
49 }
50
51 pub fn is_none(&self) -> bool {
53 self.0.is_reserved_value()
54 }
55
56 pub fn is_some(&self) -> bool {
58 !self.0.is_reserved_value()
59 }
60
61 pub fn expand(self) -> Option<T> {
63 if self.is_none() { None } else { Some(self.0) }
64 }
65
66 pub fn map<U, F>(self, f: F) -> Option<U>
68 where
69 F: FnOnce(T) -> U,
70 {
71 self.expand().map(f)
72 }
73
74 #[track_caller]
76 pub fn unwrap(self) -> T {
77 self.expand().unwrap()
78 }
79
80 #[track_caller]
82 pub fn expect(self, msg: &str) -> T {
83 self.expand().expect(msg)
84 }
85
86 pub fn take(&mut self) -> Option<T> {
88 mem::replace(self, None.into()).expand()
89 }
90}
91
92impl<T: ReservedValue> Default for PackedOption<T> {
93 fn default() -> Self {
95 Self(T::reserved_value())
96 }
97}
98
99impl<T: ReservedValue> From<T> for PackedOption<T> {
100 fn from(t: T) -> Self {
102 debug_assert!(
103 !t.is_reserved_value(),
104 "Can't make a PackedOption from the reserved value."
105 );
106 Self(t)
107 }
108}
109
110impl<T: ReservedValue> From<Option<T>> for PackedOption<T> {
111 fn from(opt: Option<T>) -> Self {
113 match opt {
114 None => Self::default(),
115 Some(t) => t.into(),
116 }
117 }
118}
119
120impl<T: ReservedValue> From<PackedOption<T>> for Option<T> {
121 fn from(packed: PackedOption<T>) -> Option<T> {
122 packed.expand()
123 }
124}
125
126impl<T> fmt::Debug for PackedOption<T>
127where
128 T: ReservedValue + fmt::Debug,
129{
130 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131 if self.is_none() {
132 write!(f, "None")
133 } else {
134 write!(f, "Some({:?})", self.0)
135 }
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[derive(Debug, PartialEq, Eq)]
145 struct NoC(u32);
146
147 impl ReservedValue for NoC {
148 fn reserved_value() -> Self {
149 NoC(13)
150 }
151
152 fn is_reserved_value(&self) -> bool {
153 self.0 == 13
154 }
155 }
156
157 #[test]
158 fn moves() {
159 let x = NoC(3);
160 let somex: PackedOption<NoC> = x.into();
161 assert!(!somex.is_none());
162 assert_eq!(somex.expand(), Some(NoC(3)));
163
164 let none: PackedOption<NoC> = None.into();
165 assert!(none.is_none());
166 assert_eq!(none.expand(), None);
167 }
168
169 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
171 struct Ent(u32);
172
173 impl ReservedValue for Ent {
174 fn reserved_value() -> Self {
175 Ent(13)
176 }
177
178 fn is_reserved_value(&self) -> bool {
179 self.0 == 13
180 }
181 }
182
183 #[test]
184 fn copies() {
185 let x = Ent(2);
186 let some: PackedOption<Ent> = x.into();
187 assert_eq!(some.expand(), x.into());
188 assert_eq!(some, x.into());
189 }
190}