use std::fmt;
use std::string::FromUtf8Error;
use std::str::Utf8Error;
use std::ptr;
use crate::sys::napi_status;
use crate::sys::napi_value;
use crate::val::JsEnv;
use crate::IntoJs;
#[derive(Debug)]
pub enum NjError {
NapiCall(NapiStatus),
InvalidArgCount(usize, usize),
InvalidArgIndex(usize, usize),
InvalidType(String, String),
NoPlainConstructor,
Utf8Error(FromUtf8Error),
Utf8ErrorSlice(Utf8Error),
Native(napi_value),
Other(String),
}
impl IntoJs for NjError {
fn into_js(self, js_env: &JsEnv) -> napi_value {
match self {
NjError::Native(err) => {
js_env.throw(err);
ptr::null_mut()
}
_ => {
let msg = self.to_string();
js_env.throw_type_error(&msg);
ptr::null_mut()
}
}
}
}
impl NjError {
pub fn as_js(&self, js_env: &JsEnv) -> napi_value {
match self {
NjError::Native(err) => *err,
_ => {
let msg = self.to_string();
js_env.create_error(&msg).expect("error cannot be created")
}
}
}
}
impl IntoJs for Result<napi_value, NjError> {
fn into_js(self, js_env: &JsEnv) -> napi_value {
match self {
Ok(napi_val) => napi_val,
Err(err) => err.into_js(js_env),
}
}
}
impl From<FromUtf8Error> for NjError {
fn from(error: FromUtf8Error) -> Self {
Self::Utf8Error(error)
}
}
impl From<Utf8Error> for NjError {
fn from(error: Utf8Error) -> Self {
Self::Utf8ErrorSlice(error)
}
}
impl From<NapiStatus> for NjError {
fn from(status: NapiStatus) -> Self {
Self::NapiCall(status)
}
}
impl fmt::Display for NjError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::NapiCall(status) => write!(f, "napi call failed {status:#?}"),
Self::InvalidType(expected, actual) => {
write!(f, "invalid type, expected: {expected}, actual: {actual}")
}
Self::Utf8Error(err) => write!(f, "ut8 error: {err}"),
Self::Utf8ErrorSlice(err) => write!(f, "ut8 error: {err}"),
Self::InvalidArgIndex(index, len) => {
write!(f, "attempt to access arg: {index} out of len: {len}")
}
Self::InvalidArgCount(actual_count, expected_count) => write!(
f,
"{expected_count} args expected but {actual_count} is present"
),
Self::NoPlainConstructor => write!(f, "Plain constructor not supported yet"),
Self::Native(_val) => write!(f, "Native error payload"),
Self::Other(msg) => write!(f, "{msg}"),
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum NapiStatus {
Ok = crate::sys::napi_status_napi_ok as isize,
InvalidArg = crate::sys::napi_status_napi_invalid_arg as isize,
ObjectExpected = crate::sys::napi_status_napi_object_expected as isize,
StringExpected = crate::sys::napi_status_napi_string_expected as isize,
NameExpected = crate::sys::napi_status_napi_name_expected as isize,
FunctionExpected = crate::sys::napi_status_napi_function_expected as isize,
NumberExpected = crate::sys::napi_status_napi_number_expected as isize,
BooleanExpected = crate::sys::napi_status_napi_boolean_expected as isize,
ArrayExpected = crate::sys::napi_status_napi_array_expected as isize,
GenericFailure = crate::sys::napi_status_napi_generic_failure as isize,
PendingException = crate::sys::napi_status_napi_pending_exception as isize,
Cancelled = crate::sys::napi_status_napi_cancelled as isize,
EscapeCalledTwice = crate::sys::napi_status_napi_escape_called_twice as isize,
HandleScopeMismatch = crate::sys::napi_status_napi_handle_scope_mismatch as isize,
CallbackScopeMismatch = crate::sys::napi_status_napi_callback_scope_mismatch as isize,
QueueFull = crate::sys::napi_status_napi_queue_full as isize,
Closing = crate::sys::napi_status_napi_closing as isize,
BigintExpected = crate::sys::napi_status_napi_bigint_expected as isize,
DateExpected = crate::sys::napi_status_napi_date_expected as isize,
ArraybufferExpected = crate::sys::napi_status_napi_arraybuffer_expected as isize,
DetachableArrayBufferExpected =
crate::sys::napi_status_napi_detachable_arraybuffer_expected as isize,
}
impl From<napi_status> for NapiStatus {
fn from(status: napi_status) -> Self {
match status {
crate::sys::napi_status_napi_ok => Self::Ok,
crate::sys::napi_status_napi_invalid_arg => Self::InvalidArg,
crate::sys::napi_status_napi_object_expected => Self::ObjectExpected,
crate::sys::napi_status_napi_string_expected => Self::StringExpected,
crate::sys::napi_status_napi_name_expected => Self::NameExpected,
crate::sys::napi_status_napi_function_expected => Self::FunctionExpected,
crate::sys::napi_status_napi_number_expected => Self::NumberExpected,
crate::sys::napi_status_napi_boolean_expected => Self::BooleanExpected,
crate::sys::napi_status_napi_array_expected => Self::ArrayExpected,
crate::sys::napi_status_napi_generic_failure => Self::GenericFailure,
crate::sys::napi_status_napi_pending_exception => Self::PendingException,
crate::sys::napi_status_napi_cancelled => Self::Cancelled,
crate::sys::napi_status_napi_escape_called_twice => Self::EscapeCalledTwice,
crate::sys::napi_status_napi_handle_scope_mismatch => Self::HandleScopeMismatch,
crate::sys::napi_status_napi_callback_scope_mismatch => Self::CallbackScopeMismatch,
crate::sys::napi_status_napi_queue_full => Self::QueueFull,
crate::sys::napi_status_napi_closing => Self::Closing,
crate::sys::napi_status_napi_bigint_expected => Self::BigintExpected,
crate::sys::napi_status_napi_date_expected => Self::DateExpected,
crate::sys::napi_status_napi_arraybuffer_expected => Self::ArraybufferExpected,
crate::sys::napi_status_napi_detachable_arraybuffer_expected => {
Self::DetachableArrayBufferExpected
}
_ => panic!("cannot convert: {}", status),
}
}
}