1use crate::convert::UpcastFrom;
7use crate::JsCast;
8use crate::JsGeneric;
9use crate::JsValue;
10use core::fmt;
11use core::mem::ManuallyDrop;
12use core::ops::Deref;
13use wasm_bindgen_macro::wasm_bindgen;
14
15pub trait Promising {
25 type Resolution;
27}
28
29#[wasm_bindgen(wasm_bindgen = crate)]
31extern "C" {
32 #[wasm_bindgen(is_type_of = JsValue::is_undefined, typescript_type = "undefined", no_upcast)]
37 #[derive(Clone, PartialEq)]
38 pub type Undefined;
39}
40
41impl Undefined {
42 pub const UNDEFINED: Undefined = Self {
44 obj: JsValue::UNDEFINED,
45 };
46}
47
48impl Eq for Undefined {}
49
50impl Default for Undefined {
51 fn default() -> Self {
52 Self::UNDEFINED
53 }
54}
55
56impl fmt::Debug for Undefined {
57 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58 f.write_str("undefined")
59 }
60}
61
62impl fmt::Display for Undefined {
63 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64 f.write_str("undefined")
65 }
66}
67
68impl UpcastFrom<Undefined> for Undefined {}
69impl UpcastFrom<()> for Undefined {}
70impl UpcastFrom<Undefined> for () {}
71impl UpcastFrom<Undefined> for JsValue {}
72
73#[wasm_bindgen(wasm_bindgen = crate)]
75extern "C" {
76 #[wasm_bindgen(is_type_of = JsValue::is_null, typescript_type = "null", no_upcast)]
81 #[derive(Clone, PartialEq)]
82 pub type Null;
83}
84
85impl Null {
86 pub const NULL: Null = Self { obj: JsValue::NULL };
88}
89
90impl Eq for Null {}
91
92impl Default for Null {
93 fn default() -> Self {
94 Self::NULL
95 }
96}
97
98impl fmt::Debug for Null {
99 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100 f.write_str("null")
101 }
102}
103
104impl fmt::Display for Null {
105 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106 f.write_str("null")
107 }
108}
109
110impl UpcastFrom<Null> for Null {}
111impl UpcastFrom<Null> for JsValue {}
112
113#[wasm_bindgen(wasm_bindgen = crate)]
115extern "C" {
116 #[wasm_bindgen(typescript_type = "any", no_upcast)]
129 #[derive(Clone, PartialEq)]
130 pub type JsOption<T>;
131}
132
133impl<T> JsOption<T> {
134 #[inline]
136 pub fn new() -> Self {
137 Null::NULL.unchecked_into()
138 }
139
140 #[inline]
142 pub fn wrap(val: T) -> Self {
143 unsafe { core::mem::transmute_copy(&ManuallyDrop::new(val)) }
144 }
145
146 #[inline]
150 pub fn from_option(opt: Option<T>) -> Self {
151 match opt {
152 Some(val) => Self::wrap(val),
153 None => Self::new(),
154 }
155 }
156
157 #[inline]
159 pub fn is_empty(&self) -> bool {
160 JsValue::is_null_or_undefined(self)
161 }
162
163 #[inline]
168 pub fn as_option(&self) -> Option<T> {
169 if JsValue::is_null_or_undefined(self) {
170 None
171 } else {
172 let cloned = self.deref().clone();
173 Some(unsafe { core::mem::transmute_copy(&ManuallyDrop::new(cloned)) })
174 }
175 }
176
177 #[inline]
182 pub fn into_option(self) -> Option<T> {
183 if JsValue::is_null_or_undefined(&self) {
184 None
185 } else {
186 Some(unsafe { core::mem::transmute_copy(&ManuallyDrop::new(self)) })
187 }
188 }
189
190 #[inline]
196 pub fn unwrap(self) -> T {
197 self.expect("called `JsOption::unwrap()` on an empty value")
198 }
199
200 #[inline]
207 pub fn expect(self, msg: &str) -> T {
208 match self.into_option() {
209 Some(val) => val,
210 None => panic!("{}", msg),
211 }
212 }
213
214 #[inline]
219 pub fn unwrap_or_default(self) -> T
220 where
221 T: Default,
222 {
223 self.into_option().unwrap_or_default()
224 }
225
226 #[inline]
231 pub fn unwrap_or_else<F>(self, f: F) -> T
232 where
233 F: FnOnce() -> T,
234 {
235 self.into_option().unwrap_or_else(f)
236 }
237}
238
239impl<T: JsGeneric> Default for JsOption<T> {
240 fn default() -> Self {
241 Self::new()
242 }
243}
244
245impl<T: JsGeneric + fmt::Debug> fmt::Debug for JsOption<T> {
246 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
247 write!(f, "{}?(", core::any::type_name::<T>())?;
248 match self.as_option() {
249 Some(v) => write!(f, "{v:?}")?,
250 None => f.write_str("null")?,
251 }
252 f.write_str(")")
253 }
254}
255
256impl<T: JsGeneric + fmt::Display> fmt::Display for JsOption<T> {
257 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
258 write!(f, "{}?(", core::any::type_name::<T>())?;
259 match self.as_option() {
260 Some(v) => write!(f, "{v}")?,
261 None => f.write_str("null")?,
262 }
263 f.write_str(")")
264 }
265}
266
267impl UpcastFrom<JsValue> for JsOption<JsValue> {}
268impl<T> UpcastFrom<Undefined> for JsOption<T> {}
269impl<T> UpcastFrom<Null> for JsOption<T> {}
270impl<T> UpcastFrom<()> for JsOption<T> {}
271impl<T> UpcastFrom<JsOption<T>> for JsValue {}
272impl<T, U> UpcastFrom<JsOption<U>> for JsOption<T> where T: UpcastFrom<U> {}