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