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 = unsafe { core::mem::transmute(JsValue::UNDEFINED) };
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 = unsafe { core::mem::transmute(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)]
127 #[derive(Clone, PartialEq)]
128 pub type JsOption<T>;
129}
130
131impl<T> JsOption<T> {
132 #[inline]
134 pub fn new() -> Self {
135 Null::NULL.unchecked_into()
136 }
137
138 #[inline]
140 pub fn wrap(val: T) -> Self {
141 unsafe { core::mem::transmute_copy(&ManuallyDrop::new(val)) }
142 }
143
144 #[inline]
148 pub fn from_option(opt: Option<T>) -> Self {
149 match opt {
150 Some(val) => Self::wrap(val),
151 None => Self::new(),
152 }
153 }
154
155 #[inline]
157 pub fn is_empty(&self) -> bool {
158 JsValue::is_null_or_undefined(self)
159 }
160
161 #[inline]
166 pub fn as_option(&self) -> Option<T> {
167 if JsValue::is_null_or_undefined(self) {
168 None
169 } else {
170 let cloned = self.deref().clone();
171 Some(unsafe { core::mem::transmute_copy(&ManuallyDrop::new(cloned)) })
172 }
173 }
174
175 #[inline]
180 pub fn into_option(self) -> Option<T> {
181 if JsValue::is_null_or_undefined(&self) {
182 None
183 } else {
184 Some(unsafe { core::mem::transmute_copy(&ManuallyDrop::new(self)) })
185 }
186 }
187
188 #[inline]
194 pub fn unwrap(self) -> T {
195 self.expect("called `JsOption::unwrap()` on an empty value")
196 }
197
198 #[inline]
205 pub fn expect(self, msg: &str) -> T {
206 match self.into_option() {
207 Some(val) => val,
208 None => panic!("{}", msg),
209 }
210 }
211
212 #[inline]
217 pub fn unwrap_or_default(self) -> T
218 where
219 T: Default,
220 {
221 self.into_option().unwrap_or_default()
222 }
223
224 #[inline]
229 pub fn unwrap_or_else<F>(self, f: F) -> T
230 where
231 F: FnOnce() -> T,
232 {
233 self.into_option().unwrap_or_else(f)
234 }
235}
236
237impl<T: JsGeneric> Default for JsOption<T> {
238 fn default() -> Self {
239 Self::new()
240 }
241}
242
243impl<T: JsGeneric + fmt::Debug> fmt::Debug for JsOption<T> {
244 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
245 write!(f, "{}?(", core::any::type_name::<T>())?;
246 match self.as_option() {
247 Some(v) => write!(f, "{v:?}")?,
248 None => f.write_str("null")?,
249 }
250 f.write_str(")")
251 }
252}
253
254impl<T: JsGeneric + fmt::Display> fmt::Display for JsOption<T> {
255 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
256 write!(f, "{}?(", core::any::type_name::<T>())?;
257 match self.as_option() {
258 Some(v) => write!(f, "{v}")?,
259 None => f.write_str("null")?,
260 }
261 f.write_str(")")
262 }
263}
264
265impl UpcastFrom<JsValue> for JsOption<JsValue> {}
266impl<T> UpcastFrom<Undefined> for JsOption<T> {}
267impl<T> UpcastFrom<Null> for JsOption<T> {}
268impl<T> UpcastFrom<()> for JsOption<T> {}
269impl<T> UpcastFrom<JsOption<T>> for JsValue {}
270impl<T, U> UpcastFrom<JsOption<U>> for JsOption<T> where T: UpcastFrom<U> {}