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
24impl 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 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}