ferrijs_std/utils/
option.rs1use rquickjs::{
2 class::{Trace, Tracer},
3 function::{FromParam, ParamRequirement, ParamsAccessor},
4 Ctx, FromJs, IntoJs, JsLifetime, Result, Type, Value,
5};
6
7#[derive(Clone)]
9pub struct Undefined<T>(pub Option<T>);
10
11impl<'js, T: FromJs<'js>> FromJs<'js> for Undefined<T> {
12 fn from_js(ctx: &Ctx<'js>, value: Value<'js>) -> Result<Self> {
13 if value.type_of() == Type::Undefined {
14 Ok(Self(None))
15 } else {
16 Ok(Self(Some(FromJs::from_js(ctx, value)?)))
17 }
18 }
19}
20
21impl<'js, T: IntoJs<'js>> IntoJs<'js> for Undefined<T> {
22 fn into_js(self, ctx: &Ctx<'js>) -> Result<Value<'js>> {
23 match self.0 {
24 None => Ok(Value::new_undefined(ctx.clone())),
25 Some(val) => val.into_js(ctx),
26 }
27 }
28}
29
30impl<T> Default for Undefined<T> {
31 fn default() -> Self {
32 Self(None)
33 }
34}
35
36unsafe impl<'js, T: JsLifetime<'js>> JsLifetime<'js> for Undefined<T> {
37 type Changed<'to> = Undefined<T::Changed<'to>>;
38}
39
40impl<'js, T: Trace<'js>> Trace<'js> for Undefined<T> {
41 fn trace<'a>(&self, tracer: Tracer<'a, 'js>) {
42 self.0.trace(tracer)
43 }
44}
45
46#[derive(Clone)]
49pub struct Null<T>(pub Option<T>);
50
51impl<'js, T: FromJs<'js>> FromJs<'js> for Null<T> {
52 fn from_js(ctx: &Ctx<'js>, value: Value<'js>) -> Result<Self> {
53 if value.type_of() == Type::Null {
54 Ok(Self(None))
55 } else {
56 Ok(Self(Some(FromJs::from_js(ctx, value)?)))
57 }
58 }
59}
60
61impl<'js, T: IntoJs<'js>> IntoJs<'js> for Null<T> {
62 fn into_js(self, ctx: &Ctx<'js>) -> Result<Value<'js>> {
63 match self.0 {
64 None => Ok(Value::new_null(ctx.clone())),
65 Some(val) => val.into_js(ctx),
66 }
67 }
68}
69
70unsafe impl<'js, T: JsLifetime<'js>> JsLifetime<'js> for Null<T> {
71 type Changed<'to> = Null<T::Changed<'to>>;
72}
73
74impl<'js, T: Trace<'js>> Trace<'js> for Null<T> {
75 fn trace<'a>(&self, tracer: Tracer<'a, 'js>) {
76 self.0.trace(tracer)
77 }
78}
79
80pub struct NullableOpt<T>(pub Option<T>);
82
83impl<'js, T: FromJs<'js>> FromParam<'js> for NullableOpt<T> {
84 fn param_requirement() -> ParamRequirement {
85 ParamRequirement::optional()
86 }
87
88 fn from_param<'a>(params: &mut ParamsAccessor<'a, 'js>) -> Result<Self> {
89 if !params.is_empty() {
90 let arg = params.arg();
91 if arg.is_null() {
92 Ok(NullableOpt(None))
93 } else {
94 let ctx = params.ctx().clone();
95 Ok(NullableOpt(Some(T::from_js(&ctx, arg)?)))
96 }
97 } else {
98 Ok(NullableOpt(None))
99 }
100 }
101}