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