use crate::convert::UpcastFrom;
use crate::JsCast;
use crate::JsGeneric;
use crate::JsValue;
use core::fmt;
use core::ops::Deref;
use wasm_bindgen_macro::wasm_bindgen;
pub trait Promising {
type Resolution;
}
#[wasm_bindgen(wasm_bindgen = crate)]
extern "C" {
#[wasm_bindgen(is_type_of = JsValue::is_undefined, typescript_type = "undefined", no_upcast)]
#[derive(Clone, PartialEq)]
pub type Undefined;
}
impl Undefined {
pub const UNDEFINED: Undefined = Self {
obj: JsValue::UNDEFINED,
};
}
impl Eq for Undefined {}
impl Default for Undefined {
fn default() -> Self {
Self::UNDEFINED
}
}
impl fmt::Debug for Undefined {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("undefined")
}
}
impl fmt::Display for Undefined {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("undefined")
}
}
impl UpcastFrom<Undefined> for Undefined {}
impl UpcastFrom<()> for Undefined {}
impl UpcastFrom<Undefined> for () {}
impl UpcastFrom<Undefined> for JsValue {}
#[wasm_bindgen(wasm_bindgen = crate)]
extern "C" {
#[wasm_bindgen(is_type_of = JsValue::is_null, typescript_type = "null", no_upcast)]
#[derive(Clone, PartialEq)]
pub type Null;
}
impl Null {
pub const NULL: Null = Self { obj: JsValue::NULL };
}
impl Eq for Null {}
impl Default for Null {
fn default() -> Self {
Self::NULL
}
}
impl fmt::Debug for Null {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("null")
}
}
impl fmt::Display for Null {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("null")
}
}
impl UpcastFrom<Null> for Null {}
impl UpcastFrom<Null> for JsValue {}
#[wasm_bindgen(wasm_bindgen = crate)]
extern "C" {
#[wasm_bindgen(typescript_type = "any", no_upcast)]
#[derive(Clone, PartialEq)]
pub type JsOption<T>;
}
impl<T: JsGeneric> JsOption<T> {
#[inline]
pub fn new() -> Self {
Undefined::UNDEFINED.unchecked_into()
}
#[inline]
pub fn wrap(val: T) -> Self {
val.unchecked_into()
}
#[inline]
pub fn from_option(opt: Option<T>) -> Self {
match opt {
Some(val) => Self::wrap(val),
None => Self::new(),
}
}
#[inline]
pub fn is_empty(&self) -> bool {
JsValue::is_null_or_undefined(self)
}
#[inline]
pub fn as_option(&self) -> Option<T> {
if JsValue::is_null_or_undefined(self) {
None
} else {
let cloned = self.deref().clone();
Some(cloned.unchecked_into())
}
}
#[inline]
pub fn into_option(self) -> Option<T> {
if JsValue::is_null_or_undefined(&self) {
None
} else {
Some(self.unchecked_into())
}
}
#[inline]
pub fn unwrap(self) -> T {
self.expect("called `JsOption::unwrap()` on an empty value")
}
#[inline]
pub fn expect(self, msg: &str) -> T {
match self.into_option() {
Some(val) => val,
None => panic!("{}", msg),
}
}
#[inline]
pub fn unwrap_or_default(self) -> T
where
T: Default,
{
self.into_option().unwrap_or_default()
}
#[inline]
pub fn unwrap_or_else<F>(self, f: F) -> T
where
F: FnOnce() -> T,
{
self.into_option().unwrap_or_else(f)
}
}
impl<T: JsGeneric> Default for JsOption<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: JsGeneric + fmt::Debug> fmt::Debug for JsOption<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}?(", core::any::type_name::<T>())?;
match self.as_option() {
Some(v) => write!(f, "{v:?}")?,
None => f.write_str("null")?,
}
f.write_str(")")
}
}
impl<T: JsGeneric + fmt::Display> fmt::Display for JsOption<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}?(", core::any::type_name::<T>())?;
match self.as_option() {
Some(v) => write!(f, "{v}")?,
None => f.write_str("null")?,
}
f.write_str(")")
}
}
impl UpcastFrom<JsValue> for JsOption<JsValue> {}
impl<T> UpcastFrom<Undefined> for JsOption<T> {}
impl<T> UpcastFrom<Null> for JsOption<T> {}
impl<T> UpcastFrom<()> for JsOption<T> {}
impl<T> UpcastFrom<JsOption<T>> for JsValue {}
impl<T, U> UpcastFrom<JsOption<U>> for JsOption<T> where T: UpcastFrom<U> {}