nj_core/
error.rs

1use std::fmt;
2use std::string::FromUtf8Error;
3use std::str::Utf8Error;
4use std::ptr;
5
6use crate::sys::napi_status;
7use crate::sys::napi_value;
8use crate::val::JsEnv;
9use crate::IntoJs;
10
11#[derive(Debug)]
12pub enum NjError {
13    NapiCall(NapiStatus),
14    InvalidArgCount(usize, usize),
15    InvalidArgIndex(usize, usize),
16    InvalidType(String, String),
17    NoPlainConstructor,
18    Utf8Error(FromUtf8Error),
19    Utf8ErrorSlice(Utf8Error),
20    Native(napi_value),
21    Other(String),
22}
23
24// errors are thrown
25impl IntoJs for NjError {
26    fn into_js(self, js_env: &JsEnv) -> napi_value {
27        match self {
28            NjError::Native(err) => {
29                js_env.throw(err);
30                ptr::null_mut()
31            }
32            _ => {
33                let msg = self.to_string();
34                js_env.throw_type_error(&msg);
35                ptr::null_mut()
36            }
37        }
38    }
39}
40
41impl NjError {
42    /// convert to napi value
43    pub fn as_js(&self, js_env: &JsEnv) -> napi_value {
44        match self {
45            NjError::Native(err) => *err,
46            _ => {
47                let msg = self.to_string();
48                js_env.create_error(&msg).expect("error cannot be created")
49            }
50        }
51    }
52}
53
54impl IntoJs for Result<napi_value, NjError> {
55    fn into_js(self, js_env: &JsEnv) -> napi_value {
56        match self {
57            Ok(napi_val) => napi_val,
58            Err(err) => err.into_js(js_env),
59        }
60    }
61}
62
63impl From<FromUtf8Error> for NjError {
64    fn from(error: FromUtf8Error) -> Self {
65        Self::Utf8Error(error)
66    }
67}
68
69impl From<Utf8Error> for NjError {
70    fn from(error: Utf8Error) -> Self {
71        Self::Utf8ErrorSlice(error)
72    }
73}
74
75impl From<NapiStatus> for NjError {
76    fn from(status: NapiStatus) -> Self {
77        Self::NapiCall(status)
78    }
79}
80
81impl fmt::Display for NjError {
82    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83        match self {
84            Self::NapiCall(status) => write!(f, "napi call failed {status:#?}"),
85            Self::InvalidType(expected, actual) => {
86                write!(f, "invalid type, expected: {expected}, actual: {actual}")
87            }
88            Self::Utf8Error(err) => write!(f, "ut8 error: {err}"),
89            Self::Utf8ErrorSlice(err) => write!(f, "ut8 error: {err}"),
90            Self::InvalidArgIndex(index, len) => {
91                write!(f, "attempt to access arg: {index} out of len: {len}")
92            }
93            Self::InvalidArgCount(actual_count, expected_count) => write!(
94                f,
95                "{expected_count} args expected but {actual_count} is present"
96            ),
97            Self::NoPlainConstructor => write!(f, "Plain constructor not supported yet"),
98            Self::Native(_val) => write!(f, "Native error payload"),
99            Self::Other(msg) => write!(f, "{msg}"),
100        }
101    }
102}
103
104#[derive(Debug, PartialEq, Eq)]
105pub enum NapiStatus {
106    Ok = crate::sys::napi_status_napi_ok as isize,
107    InvalidArg = crate::sys::napi_status_napi_invalid_arg as isize,
108    ObjectExpected = crate::sys::napi_status_napi_object_expected as isize,
109    StringExpected = crate::sys::napi_status_napi_string_expected as isize,
110    NameExpected = crate::sys::napi_status_napi_name_expected as isize,
111    FunctionExpected = crate::sys::napi_status_napi_function_expected as isize,
112    NumberExpected = crate::sys::napi_status_napi_number_expected as isize,
113    BooleanExpected = crate::sys::napi_status_napi_boolean_expected as isize,
114    ArrayExpected = crate::sys::napi_status_napi_array_expected as isize,
115    GenericFailure = crate::sys::napi_status_napi_generic_failure as isize,
116    PendingException = crate::sys::napi_status_napi_pending_exception as isize,
117    Cancelled = crate::sys::napi_status_napi_cancelled as isize,
118    EscapeCalledTwice = crate::sys::napi_status_napi_escape_called_twice as isize,
119    HandleScopeMismatch = crate::sys::napi_status_napi_handle_scope_mismatch as isize,
120    CallbackScopeMismatch = crate::sys::napi_status_napi_callback_scope_mismatch as isize,
121    QueueFull = crate::sys::napi_status_napi_queue_full as isize,
122    Closing = crate::sys::napi_status_napi_closing as isize,
123    BigintExpected = crate::sys::napi_status_napi_bigint_expected as isize,
124    DateExpected = crate::sys::napi_status_napi_date_expected as isize,
125    ArraybufferExpected = crate::sys::napi_status_napi_arraybuffer_expected as isize,
126    DetachableArrayBufferExpected =
127        crate::sys::napi_status_napi_detachable_arraybuffer_expected as isize,
128}
129
130impl From<napi_status> for NapiStatus {
131    fn from(status: napi_status) -> Self {
132        match status {
133            crate::sys::napi_status_napi_ok => Self::Ok,
134            crate::sys::napi_status_napi_invalid_arg => Self::InvalidArg,
135            crate::sys::napi_status_napi_object_expected => Self::ObjectExpected,
136            crate::sys::napi_status_napi_string_expected => Self::StringExpected,
137            crate::sys::napi_status_napi_name_expected => Self::NameExpected,
138            crate::sys::napi_status_napi_function_expected => Self::FunctionExpected,
139            crate::sys::napi_status_napi_number_expected => Self::NumberExpected,
140            crate::sys::napi_status_napi_boolean_expected => Self::BooleanExpected,
141            crate::sys::napi_status_napi_array_expected => Self::ArrayExpected,
142            crate::sys::napi_status_napi_generic_failure => Self::GenericFailure,
143            crate::sys::napi_status_napi_pending_exception => Self::PendingException,
144            crate::sys::napi_status_napi_cancelled => Self::Cancelled,
145            crate::sys::napi_status_napi_escape_called_twice => Self::EscapeCalledTwice,
146            crate::sys::napi_status_napi_handle_scope_mismatch => Self::HandleScopeMismatch,
147            crate::sys::napi_status_napi_callback_scope_mismatch => Self::CallbackScopeMismatch,
148            crate::sys::napi_status_napi_queue_full => Self::QueueFull,
149            crate::sys::napi_status_napi_closing => Self::Closing,
150            crate::sys::napi_status_napi_bigint_expected => Self::BigintExpected,
151            crate::sys::napi_status_napi_date_expected => Self::DateExpected,
152            crate::sys::napi_status_napi_arraybuffer_expected => Self::ArraybufferExpected,
153            crate::sys::napi_status_napi_detachable_arraybuffer_expected => {
154                Self::DetachableArrayBufferExpected
155            }
156            _ => panic!("cannot convert: {}", status),
157        }
158    }
159}