use crate::*;
use std::error::Error;
use std::ffi::CStr;
use std::fmt;
use std::num::TryFromIntError;
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct IonCError {
pub code: i32,
pub message: &'static str,
pub additional: &'static str,
pub position: Position,
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Position {
Unknown,
Offset(i64),
OffsetLineColumn(i64, LineColumn),
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct LineColumn(pub i32, pub i32);
impl Position {
pub fn text(bytes: i64, line: i32, offset: i32) -> Position {
Position::OffsetLineColumn(bytes, LineColumn(line, offset))
}
pub fn binary(bytes: i64) -> Position {
Position::Offset(bytes)
}
}
impl IonCError {
pub fn from(code: i32) -> Self {
Self::with_additional(code, "iERR Result")
}
pub fn with_additional(code: i32, additional: &'static str) -> Self {
match code {
ion_error_code_IERR_NOT_IMPL..=ion_error_code_IERR_INVALID_LOB_TERMINATOR => {
unsafe {
let c_str = CStr::from_ptr(ion_error_to_str(code));
let message = c_str.to_str().unwrap();
Self {
code,
message,
additional,
position: Position::Unknown,
}
}
}
_ => Self {
code,
message: "Unknown Ion C Error Code",
additional,
position: Position::Unknown,
},
}
}
pub fn with_position(mut self, pos: Position) -> Self {
self.position = pos;
self
}
}
impl fmt::Display for IonCError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Error {}: {} ({})",
self.code, self.message, self.additional
)
}
}
impl Error for IonCError {}
impl From<TryFromIntError> for IonCError {
fn from(_: TryFromIntError) -> Self {
IonCError::from(ion_error_code_IERR_NUMERIC_OVERFLOW)
}
}
impl From<Utf8Error> for IonCError {
fn from(_: Utf8Error) -> Self {
IonCError::from(ion_error_code_IERR_INVALID_UTF8)
}
}
pub type IonCResult<T> = Result<T, IonCError>;
#[macro_export]
macro_rules! ionc {
($e:expr) => {
unsafe {
let err: i32 = $e;
match err {
$crate::ion_error_code_IERR_OK => Ok(()),
code => Err($crate::result::IonCError::from(code)),
}
}
};
}