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