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> {}