use std::{error::Error as StdErr, pin::Pin, sync::Arc};
use thiserror::Error;
use crate::data::managed::{
array::dimensions::Dimensions,
value::{Value, ValueRef},
};
pub(crate) static CANNOT_DISPLAY_TYPE: &'static str = "<Cannot display type>";
pub(crate) static CANNOT_DISPLAY_VALUE: &'static str = "<Cannot display value>";
pub type JlrsResult<T> = Result<T, Box<JlrsError>>;
pub fn project_jlrs_result<T>(p: Pin<&mut JlrsResult<T>>) -> JlrsResult<Pin<&mut T>> {
unsafe {
match p.get_unchecked_mut() {
Ok(o) => Ok(Pin::new_unchecked(o)),
Err(e) => Err(e.clone())?,
}
}
}
pub type JuliaResult<'frame, 'data, V = Value<'frame, 'data>> = Result<V, Value<'frame, 'data>>;
pub type JuliaResultRef<'frame, 'data, V = ValueRef<'frame, 'data>> =
Result<V, ValueRef<'frame, 'data>>;
#[derive(Debug, Error, Clone)]
pub enum RuntimeError {
#[error("runtime can only be initialized once")]
AlreadyInitialized,
#[error("channel closed")]
ChannelClosed,
#[error("channel full")]
ChannelFull,
#[error("an active instance already exists on this thread")]
AlreadyActive,
#[error("Julia has not been initialized yet")]
Inactive,
#[error("this thread is unknown to Julia")]
InvalidThread,
#[error("the current state does not allow creating new handles")]
IncorrectState,
}
#[derive(Debug, Error, Clone)]
pub enum IOError {
#[error("path does not exist: {path}")]
NotFound { path: String },
}
#[derive(Debug, Error, Clone)]
pub enum TypeError {
#[error("expected a Function, {name} is a {ty}")]
NotAFunction { name: String, ty: String },
#[error("expected a NamedTuple, got a {ty}")]
NotANamedTuple { ty: String },
#[error("expected a Module, {name} is a {ty}")]
NotAModule { name: String, ty: String },
#[error("{element_type} is not a {value_type}")]
IncompatibleType {
element_type: String,
value_type: String,
},
#[error("{value_type} is not subtype of {field_type}")]
NotASubtype {
value_type: String,
field_type: String,
},
#[error("{value} is not a {field_type}")]
NotA { value: String, field_type: String },
#[error("{value} is not a concrete datatype")]
NotConcrete { value: String },
#[error("layout is invalid for {value_type}")]
InvalidLayout { value_type: String },
#[error("{value_type} is immutable")]
Immutable { value_type: String },
#[error("No base type is available")]
NoBaseType,
#[error("Layout of {ty} is None")]
LayoutNone { ty: String },
#[error("The layout of this type is incompatible with {base_type}")]
IncompatibleBaseType { base_type: String },
}
#[derive(Debug, Error, Clone)]
pub enum ArrayLayoutError {
#[error("element type is {element_type}, which is not a bits union")]
NotUnion { element_type: String },
#[error("element type is {element_type}, which is not stored inline")]
NotInline { element_type: String },
#[error("element type is {element_type}, which has pointer fields")]
NotBits { element_type: String },
#[error("element type is {element_type}, which is stored inline")]
NotPointer { element_type: String },
#[error("element type is {element_type}, not {name}")]
NotManaged { element_type: String, name: String },
#[error("rank must be {provided}, got {found}")]
RankMismatch { found: isize, provided: isize },
}
#[derive(Debug, Error, Clone)]
pub enum AccessError {
#[error("{type_name} has no field named {field_name}")]
NoSuchField {
type_name: String,
field_name: String,
},
#[error("modules cannot be accessed by field")]
ModuleField,
#[error("layout is invalid for {value_type}")]
InvalidLayout { value_type: String },
#[error("no value named {name} in {module}")]
GlobalNotFound { name: String, module: String },
#[error("module named {module} not found")]
ModuleNotFound { module: String },
#[error("the current value is locked")]
Locked,
#[error("{tag} is not a valid tag for {union_type}")]
IllegalUnionTag { union_type: String, tag: usize },
#[error("field {field_name} of type {value_type} is not stored as a pointer")]
NotAPointerField {
value_type: String,
field_name: String,
},
#[error("Data is already borrowed")]
BorrowError,
#[error("field at index {idx} does not exist: {value_type} has {n_fields} fields")]
OutOfBoundsField {
idx: usize,
n_fields: usize,
value_type: String,
},
#[error("index {idx} is out-of-bounds for SimpleVector of length {len}")]
OutOfBoundsSVec { idx: usize, len: usize },
#[error("index {idx} is invalid for array with shape {sz}")]
InvalidIndex { idx: Dimensions, sz: Dimensions },
#[error("arrays can only be accessed with n-dimensional indices")]
ArrayNeedsNumericalIndex,
#[error("fields cannot be accessed with n-dimensional indices")]
FieldNeedsSimpleIndex,
#[error("cannot access undefined reference")]
UndefRef,
#[error("type {value_type} has no fields")]
NoFields { value_type: String },
}
#[derive(Debug, Error, Clone)]
pub enum InstantiationError {
#[error("cannot create array with DataType::instantiate")]
ArrayNotSupported,
#[error("NamedTuples must have an equal number of keys and values, got {n_names} keys and {n_values} values")]
NamedTupleSizeMismatch { n_names: usize, n_values: usize },
#[error("expected a shape for {vec_size} elements, got a shape for {dim_size} elements")]
ArraySizeMismatch { dim_size: usize, vec_size: usize },
#[error("expected dimensions of rank {expected}, got {found}")]
ArrayRankMismatch { expected: usize, found: usize },
}
#[derive(Debug, Error, Clone)]
#[error("{msg}")]
pub struct Exception {
msg: String,
}
impl Exception {
pub fn get_message(&self) -> &str {
&self.msg
}
}
#[derive(Debug, Error, Clone)]
pub enum JlrsError {
#[error("Other: {0}")]
Other(Arc<dyn StdErr + 'static + Send + Sync>),
#[error("Exception: {0}")]
Exception(Exception),
#[error("Runtime error: {0}")]
RuntimeError(RuntimeError),
#[error("Type error: {0}")]
TypeError(TypeError),
#[error("IO error: {0}")]
IOError(IOError),
#[error("Access error: {0}")]
AccessError(AccessError),
#[error("Instantiation error: {0}")]
InstantiationError(InstantiationError),
#[error("Array layout error: {0}")]
ArrayLayoutError(ArrayLayoutError),
}
impl JlrsError {
#[inline]
pub fn other<E: StdErr + 'static + Send + Sync>(reason: E) -> Self {
JlrsError::Other(Arc::new(reason))
}
#[inline]
pub fn exception<S: Into<String>>(msg: S) -> Self {
JlrsError::Exception(Exception { msg: msg.into() })
}
#[inline]
pub fn other_error<T, E: StdErr + 'static + Send + Sync>(reason: E) -> Result<T, Self> {
Err(Self::other(reason))
}
#[inline]
pub fn exception_error<T>(msg: String) -> Result<T, Self> {
Err(JlrsError::exception(msg))
}
}
macro_rules! impl_from {
($type:ident) => {
impl From<$type> for JlrsError {
#[inline]
fn from(e: $type) -> Self {
JlrsError::$type(e)
}
}
impl From<$type> for Box<JlrsError> {
#[inline]
fn from(e: $type) -> Self {
Box::new(JlrsError::from(e))
}
}
};
}
impl_from!(RuntimeError);
impl_from!(TypeError);
impl_from!(IOError);
impl_from!(AccessError);
impl_from!(InstantiationError);
impl_from!(ArrayLayoutError);