use crate::raw::{self, Raw};
use rayforce_sys as sys;
use std::ffi::CStr;
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ErrorCode {
Oom,
Type,
Range,
Length,
Rank,
Domain,
Nyi,
Io,
Schema,
Corrupt,
Cancel,
Parse,
Name,
Limit,
Other,
}
impl ErrorCode {
fn from_err_t(e: sys::ray_err_t) -> Self {
match e {
sys::ray_err_t_RAY_ERR_OOM => ErrorCode::Oom,
sys::ray_err_t_RAY_ERR_TYPE => ErrorCode::Type,
sys::ray_err_t_RAY_ERR_RANGE => ErrorCode::Range,
sys::ray_err_t_RAY_ERR_LENGTH => ErrorCode::Length,
sys::ray_err_t_RAY_ERR_RANK => ErrorCode::Rank,
sys::ray_err_t_RAY_ERR_DOMAIN => ErrorCode::Domain,
sys::ray_err_t_RAY_ERR_NYI => ErrorCode::Nyi,
sys::ray_err_t_RAY_ERR_IO => ErrorCode::Io,
sys::ray_err_t_RAY_ERR_SCHEMA => ErrorCode::Schema,
sys::ray_err_t_RAY_ERR_CORRUPT => ErrorCode::Corrupt,
sys::ray_err_t_RAY_ERR_CANCEL => ErrorCode::Cancel,
sys::ray_err_t_RAY_ERR_PARSE => ErrorCode::Parse,
sys::ray_err_t_RAY_ERR_NAME => ErrorCode::Name,
sys::ray_err_t_RAY_ERR_LIMIT => ErrorCode::Limit,
_ => ErrorCode::Other,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RayError {
pub code: ErrorCode,
pub code_str: String,
pub message: String,
}
impl RayError {
pub(crate) fn binding(message: impl Into<String>) -> Self {
RayError {
code: ErrorCode::Other,
code_str: String::new(),
message: message.into(),
}
}
pub(crate) unsafe fn from_obj(err: Raw) -> Self {
let code = ErrorCode::from_err_t(sys::ray_err_from_obj(err));
let code_str = cstr_to_string(sys::ray_err_code(err));
let message = cstr_to_string(sys::ray_error_msg());
sys::ray_error_free(err);
RayError {
code,
code_str,
message,
}
}
}
impl fmt::Display for RayError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let label = if self.code_str.is_empty() {
"rayforce error"
} else {
&self.code_str
};
if self.message.is_empty() {
write!(f, "{label}")
} else {
write!(f, "{label}: {}", self.message)
}
}
}
impl std::error::Error for RayError {}
pub type Result<T> = std::result::Result<T, RayError>;
unsafe fn cstr_to_string(p: *const std::os::raw::c_char) -> String {
if p.is_null() {
String::new()
} else {
CStr::from_ptr(p).to_string_lossy().into_owned()
}
}
pub(crate) unsafe fn check(v: Raw) -> Result<Raw> {
if raw::is_err(v) {
Err(RayError::from_obj(v))
} else {
Ok(v)
}
}
const RAY_LAZY: i8 = 104;
pub(crate) unsafe fn materialize(v: Raw) -> Result<Raw> {
if v.is_null() || raw::type_code(v) != RAY_LAZY {
return Ok(v);
}
let m = sys::ray_lazy_materialize(v);
if m.is_null() {
return Err(RayError::binding("lazy materialization failed"));
}
if raw::is_err(m) {
return Err(RayError::from_obj(m));
}
Ok(m)
}