nj-core 5.0.1

high level wrapper for Node N-API
Documentation
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),
}

// errors are thrown
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 {
    /// convert to napi value
    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),
        }
    }
}