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