neon/macro_internal/
mod.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//! Internals needed by macros. These have to be exported for the macros to work

use std::marker::PhantomData;

pub use linkme;

use crate::{
    context::{Context, Cx, ModuleContext},
    handle::Handle,
    result::{JsResult, NeonResult},
    types::{extract::TryIntoJs, JsValue},
};

#[cfg(feature = "serde")]
use crate::types::extract::Json;

#[cfg(all(feature = "napi-6", feature = "futures"))]
pub use self::futures::*;

#[cfg(all(feature = "napi-6", feature = "futures"))]
mod futures;

type Export<'cx> = (&'static str, Handle<'cx, JsValue>);

#[linkme::distributed_slice]
pub static EXPORTS: [for<'cx> fn(&mut ModuleContext<'cx>) -> NeonResult<Export<'cx>>];

#[linkme::distributed_slice]
pub static MAIN: [for<'cx> fn(ModuleContext<'cx>) -> NeonResult<()>];

// Wrapper for the value type and return type tags
pub struct NeonMarker<Tag, Return>(PhantomData<Tag>, PhantomData<Return>);

// Markers to determine the type of a value
#[cfg(feature = "serde")]
pub struct NeonJsonTag;
pub struct NeonValueTag;
pub struct NeonResultTag;

pub trait ToNeonMarker {
    type Return;

    fn to_neon_marker<Tag>(&self) -> NeonMarker<Tag, Self::Return>;
}

// Specialized implementation for `Result`
impl<T, E> ToNeonMarker for Result<T, E> {
    type Return = NeonResultTag;

    fn to_neon_marker<Tag>(&self) -> NeonMarker<Tag, Self::Return> {
        NeonMarker(PhantomData, PhantomData)
    }
}

// Default implementation that takes lower precedence due to autoref
impl<T> ToNeonMarker for &T {
    type Return = NeonValueTag;

    fn to_neon_marker<Tag>(&self) -> NeonMarker<Tag, Self::Return> {
        NeonMarker(PhantomData, PhantomData)
    }
}

impl<Return> NeonMarker<NeonValueTag, Return> {
    pub fn neon_into_js<'cx, T>(self, cx: &mut Cx<'cx>, v: T) -> JsResult<'cx, JsValue>
    where
        T: TryIntoJs<'cx>,
    {
        v.try_into_js(cx).map(|v| v.upcast())
    }
}

#[cfg(feature = "serde")]
impl NeonMarker<NeonJsonTag, NeonValueTag> {
    pub fn neon_into_js<'cx, T>(self, cx: &mut Cx<'cx>, v: T) -> JsResult<'cx, JsValue>
    where
        Json<T>: TryIntoJs<'cx>,
    {
        Json(v).try_into_js(cx).map(|v| v.upcast())
    }
}

#[cfg(feature = "serde")]
impl NeonMarker<NeonJsonTag, NeonResultTag> {
    pub fn neon_into_js<'cx, T, E>(
        self,
        cx: &mut Cx<'cx>,
        res: Result<T, E>,
    ) -> JsResult<'cx, JsValue>
    where
        Result<Json<T>, E>: TryIntoJs<'cx>,
    {
        res.map(Json).try_into_js(cx).map(|v| v.upcast())
    }
}

impl<Tag> NeonMarker<Tag, NeonValueTag> {
    pub fn into_neon_result<T>(self, _cx: &mut Cx, v: T) -> NeonResult<T> {
        Ok(v)
    }
}

impl<Tag> NeonMarker<Tag, NeonResultTag> {
    pub fn into_neon_result<'cx, T, E>(self, cx: &mut Cx<'cx>, res: Result<T, E>) -> NeonResult<T>
    where
        E: TryIntoJs<'cx>,
    {
        match res {
            Ok(v) => Ok(v),
            Err(err) => err.try_into_js(cx).and_then(|err| cx.throw(err)),
        }
    }
}