neon/types_impl/extract/
error.rsuse std::{convert::Infallible, error, fmt, marker::PhantomData};
use crate::{
context::{Context, Cx},
result::JsResult,
types::{
extract::{private, TryIntoJs},
JsError, JsValue, Value,
},
};
type BoxError = Box<dyn error::Error + Send + Sync + 'static>;
pub struct TypeExpected<T: Value>(PhantomData<T>);
impl<T: Value> TypeExpected<T> {
pub(super) fn new() -> Self {
Self(PhantomData)
}
}
impl<T: Value> fmt::Display for TypeExpected<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "expected {}", T::name())
}
}
impl<T: Value> fmt::Debug for TypeExpected<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("TypeExpected").field(&T::name()).finish()
}
}
impl<T: Value> error::Error for TypeExpected<T> {}
impl<'cx, T: Value> TryIntoJs<'cx> for TypeExpected<T> {
type Value = JsError;
fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
JsError::type_error(cx, self.to_string())
}
}
impl<T: Value> private::Sealed for TypeExpected<T> {}
impl<'cx> TryIntoJs<'cx> for Infallible {
type Value = JsValue;
fn try_into_js(self, _: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
unreachable!()
}
}
impl private::Sealed for Infallible {}
#[derive(Debug)]
pub struct Error {
cause: BoxError,
kind: Option<ErrorKind>,
}
#[derive(Debug)]
enum ErrorKind {
Error,
RangeError,
TypeError,
}
impl Error {
pub fn new<E>(cause: E) -> Self
where
E: Into<BoxError>,
{
Self::create(ErrorKind::Error, cause)
}
pub fn range_error<E>(cause: E) -> Self
where
E: Into<BoxError>,
{
Self::create(ErrorKind::RangeError, cause)
}
pub fn type_error<E>(cause: E) -> Self
where
E: Into<BoxError>,
{
Self::create(ErrorKind::TypeError, cause)
}
pub fn is_range_error(&self) -> bool {
matches!(self.kind, Some(ErrorKind::RangeError))
}
pub fn is_type_error(&self) -> bool {
matches!(self.kind, Some(ErrorKind::TypeError))
}
pub fn cause(&self) -> &BoxError {
&self.cause
}
pub fn into_cause(self) -> BoxError {
self.cause
}
fn create<E>(kind: ErrorKind, cause: E) -> Self
where
E: Into<BoxError>,
{
Self {
cause: cause.into(),
kind: Some(kind),
}
}
}
impl<E> From<E> for Error
where
E: Into<BoxError>,
{
fn from(cause: E) -> Self {
Self::new(cause)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}: {}", self.kind, self.cause)
}
}
impl<'cx> TryIntoJs<'cx> for Error {
type Value = JsError;
fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
let message = self.cause.to_string();
match self.kind {
Some(ErrorKind::RangeError) => cx.range_error(message),
Some(ErrorKind::TypeError) => cx.type_error(message),
_ => cx.error(message),
}
}
}