#![warn(missing_docs)]
use std::ops::{Deref, DerefMut};
#[cfg(feature = "serde")]
mod serde;
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum JsOption<T> {
Some(T),
Null,
Undefined,
}
impl<T> JsOption<T> {
pub fn from_option(opt: Option<T>) -> Self {
match opt {
Some(val) => Self::Some(val),
None => Self::Null,
}
}
pub fn from_implicit_option(opt: Option<T>) -> Self {
match opt {
Some(val) => Self::Some(val),
None => Self::Undefined,
}
}
pub fn into_option(self) -> Option<T> {
match self {
Self::Some(val) => Some(val),
_ => None,
}
}
pub fn into_nested_option(self) -> Option<Option<T>> {
match self {
Self::Some(val) => Some(Some(val)),
Self::Null => Some(None),
Self::Undefined => None,
}
}
pub const fn is_some(&self) -> bool {
matches!(self, Self::Some(_))
}
pub const fn is_null(&self) -> bool {
matches!(self, Self::Null)
}
pub const fn is_undefined(&self) -> bool {
matches!(self, Self::Undefined)
}
#[track_caller]
pub fn unwrap(self) -> T {
match self {
Self::Some(val) => val,
Self::Null => panic!("called `JsOption::unwrap()` on `Null`"),
Self::Undefined => panic!("called `JsOption::unwrap()` on `Undefined`"),
}
}
pub fn unwrap_or(self, default: T) -> T {
match self {
Self::Some(val) => val,
_ => default,
}
}
pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
match self {
Self::Some(val) => val,
_ => f(),
}
}
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> JsOption<U> {
match self {
Self::Some(val) => JsOption::Some(f(val)),
Self::Null => JsOption::Null,
Self::Undefined => JsOption::Undefined,
}
}
pub const fn as_ref(&self) -> JsOption<&T> {
match self {
Self::Some(x) => JsOption::Some(x),
Self::Null => JsOption::Null,
Self::Undefined => JsOption::Undefined,
}
}
pub fn as_mut(&mut self) -> JsOption<&mut T> {
match self {
Self::Some(x) => JsOption::Some(x),
Self::Null => JsOption::Null,
Self::Undefined => JsOption::Undefined,
}
}
}
impl<T: Default> JsOption<T> {
pub fn unwrap_or_default(self) -> T {
self.unwrap_or_else(Default::default)
}
}
impl<T: Deref> JsOption<T> {
pub fn as_deref(&self) -> JsOption<&<T as Deref>::Target> {
self.as_ref().map(|val| val.deref())
}
}
impl<T: DerefMut> JsOption<T> {
pub fn as_deref_mut(&mut self) -> JsOption<&mut <T as Deref>::Target> {
self.as_mut().map(|val| val.deref_mut())
}
}
impl<T> Default for JsOption<T> {
fn default() -> Self {
Self::Undefined
}
}