use std::{convert::Infallible, error::Error, ffi, os::raw::c_int};
use crate::sys;
use parse_display::Display;
use thiserror::Error;
#[derive(Debug, Display, Clone)]
#[repr(u32)]
pub enum ExitCode {
Ok = sys::JIM_OK,
Err = sys::JIM_ERR,
Return = sys::JIM_RETURN,
Break = sys::JIM_BREAK,
Continue = sys::JIM_CONTINUE,
Signal = sys::JIM_SIGNAL,
Exit = sys::JIM_EXIT,
#[display("format")]
InvalidCode(u32),
}
impl From<u32> for ExitCode {
fn from(value: u32) -> Self {
match value {
sys::JIM_OK => ExitCode::Ok,
sys::JIM_ERR => ExitCode::Err,
sys::JIM_RETURN => ExitCode::Return,
sys::JIM_BREAK => ExitCode::Break,
sys::JIM_CONTINUE => ExitCode::Continue,
sys::JIM_SIGNAL => ExitCode::Signal,
sys::JIM_EXIT => ExitCode::Exit,
x => ExitCode::InvalidCode(x),
}
}
}
impl Into<c_int> for ExitCode {
fn into(self) -> c_int {
let ec: u32 = self.into();
ec as c_int
}
}
impl Into<u32> for ExitCode {
fn into(self) -> u32 {
match self {
ExitCode::Ok => sys::JIM_OK,
ExitCode::Err => sys::JIM_ERR,
ExitCode::Return => sys::JIM_RETURN,
ExitCode::Break => sys::JIM_BREAK,
ExitCode::Continue => sys::JIM_CONTINUE,
ExitCode::Signal => sys::JIM_SIGNAL,
ExitCode::Exit => sys::JIM_EXIT,
ExitCode::InvalidCode(c) => c,
}
}
}
#[derive(Error, Debug)]
pub enum JimError {
#[error("Tcl evaluation error: {0}")]
Error(String),
#[error("Tcl return code {0}")]
OtherCode(ExitCode),
#[error("Jim object is null")]
NullObject,
#[error("index {0} is out of bounds")]
InvalidIndex(usize),
#[error("object is not a dictionary")]
InvalidDictionary,
#[error("Input string has null character")]
NullCharacter,
#[error("{0}")]
Wrapped(Box<dyn Error>),
}
impl JimError {
pub fn wrap<E: Error + 'static>(err: E) -> JimError {
JimError::Wrapped(Box::new(err))
}
}
impl From<&str> for JimError {
fn from(value: &str) -> Self {
JimError::Error(value.to_owned())
}
}
impl From<String> for JimError {
fn from(value: String) -> Self {
JimError::Error(value)
}
}
impl From<Infallible> for JimError {
fn from(_value: Infallible) -> Self {
unreachable!("infallible error")
}
}
impl From<ffi::NulError> for JimError {
fn from(_value: ffi::NulError) -> Self {
JimError::NullCharacter
}
}
pub type JimResult<T> = Result<T, JimError>;