use std::ffi::CStr;
use std::fmt;
use std::ptr::NonNull;
use crate::{Confidence, ffi};
#[derive(Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum ErrorKind {
Invalid,
Io,
Format,
Language,
Grammar,
OutOfMemory,
AbiMismatch,
ParseRefused,
Unknown(i32),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Error {
pub kind: ErrorKind,
pub message: String,
pub confidence: Option<Confidence>,
}
pub type Result<T> = std::result::Result<T, Error>;
impl Error {
pub(crate) fn new(kind: ErrorKind, message: impl Into<String>) -> Self {
Self {
kind,
message: message.into(),
confidence: None,
}
}
pub(crate) fn native(status: i32) -> Self {
let kind = match status {
-1 => ErrorKind::Invalid,
-2 => ErrorKind::Io,
-3 => ErrorKind::Format,
-4 => ErrorKind::Language,
-5 => ErrorKind::Grammar,
-6 => ErrorKind::OutOfMemory,
other => ErrorKind::Unknown(other),
};
let message = unsafe { CStr::from_ptr(ffi::jnt_last_error()) }
.to_string_lossy()
.into_owned();
Self::new(kind, message)
}
pub(crate) fn status(status: i32) -> Result<()> {
if status == 0 {
Ok(())
} else {
Err(Self::native(status))
}
}
pub(crate) fn handle(pointer: *mut ffi::Handle) -> Result<NonNull<ffi::Handle>> {
NonNull::new(pointer).ok_or_else(|| {
Self::new(
ErrorKind::Format,
"libjnt returned a null successful handle",
)
})
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "{}", self.message)
}
}
impl std::error::Error for Error {}