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