neon/types_impl/extract/
boxed.rs

1use crate::{
2    context::{Context, Cx},
3    handle::Handle,
4    result::{JsResult, NeonResult},
5    types::{
6        extract::{private, TryFromJs, TryIntoJs, TypeExpected},
7        Finalize, JsBox, JsValue,
8    },
9};
10
11/// Wrapper to extract `T` from a [`JsBox<T>`](JsBox) or create a [`JsBox`]
12/// from a `T`.
13///
14/// [`Boxed`] is especially useful for exporting async functions and tasks.
15///
16/// ```
17/// # use std::sync::Arc;
18/// # use neon::{prelude::*, types::extract::Boxed};
19/// struct Greeter {
20///     greeting: String,
21/// }
22///
23/// impl Finalize for Greeter {}
24///
25/// impl Greeter {
26///     fn new(greeting: String) -> Self {
27///         Self { greeting }
28///     }
29///
30///     fn greet(&self, name: &str) -> String {
31///         format!("{}, {name}!", self.greeting)
32///     }
33/// }
34///
35/// #[neon::export]
36/// fn create_greeter(greeting: String) -> Boxed<Arc<Greeter>> {
37///     Boxed(Arc::new(Greeter::new(greeting)))
38/// }
39///
40/// #[neon::export(task)]
41/// fn greet(Boxed(greeter): Boxed<Arc<Greeter>>, name: String) -> String {
42///     greeter.greet(&name)
43/// }
44/// ```
45pub struct Boxed<T>(pub T);
46
47impl<'cx, T> TryFromJs<'cx> for Boxed<T>
48where
49    T: Clone + 'static,
50{
51    type Error = TypeExpected<JsBox<T>>;
52
53    fn try_from_js(
54        cx: &mut Cx<'cx>,
55        v: Handle<'cx, JsValue>,
56    ) -> NeonResult<Result<Self, Self::Error>> {
57        match v.downcast::<JsBox<T>, _>(cx) {
58            Ok(v) => Ok(Ok(Self(T::clone(&v)))),
59            Err(_) => Ok(Err(TypeExpected::new())),
60        }
61    }
62}
63
64impl<'cx, T> TryIntoJs<'cx> for Boxed<T>
65where
66    T: Finalize + 'static,
67{
68    type Value = JsBox<T>;
69
70    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
71        Ok(cx.boxed(self.0))
72    }
73}
74
75impl<T> private::Sealed for Boxed<T> {}