use libc::ssize_t;
use num_enum::FromPrimitive;
use std::ffi::CStr;
use std::fmt::{Display, Formatter};
use utf8proc_sys::utf8proc_errmsg;
#[derive(Debug, Clone, thiserror::Error)]
#[error("{kind}")]
pub struct Error {
kind: ErrorKind,
}
impl Error {
#[inline]
pub fn from_kind(kind: ErrorKind) -> Self {
Error { kind }
}
#[inline]
pub(crate) fn from_code(p0: ssize_t) -> Error {
ErrorKind::from_code(p0).into()
}
}
impl Error {
#[inline]
pub fn kind(&self) -> ErrorKind {
self.kind
}
}
impl From<ErrorKind> for Error {
fn from(value: ErrorKind) -> Self {
Error { kind: value }
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, FromPrimitive)]
#[repr(isize)]
#[non_exhaustive]
pub enum ErrorKind {
OutOfMemory = utf8proc_sys::UTF8PROC_ERROR_NOMEM,
StringOverflow = utf8proc_sys::UTF8PROC_ERROR_OVERFLOW,
InvalidUtf8 = utf8proc_sys::UTF8PROC_ERROR_INVALIDUTF8,
NotAssigned = utf8proc_sys::UTF8PROC_ERROR_NOTASSIGNED,
InvalidOptions = utf8proc_sys::UTF8PROC_ERROR_INVALIDOPTS,
#[doc(hidden)]
#[num_enum(default)]
Unknown = 0,
}
impl ErrorKind {
#[inline]
pub(crate) fn from_code(code: ssize_t) -> Self {
ErrorKind::from_primitive(code)
}
#[inline]
#[cold]
fn determine_msg(&self) -> &'static str {
unsafe {
CStr::from_ptr(utf8proc_errmsg(*self as ssize_t))
.to_str()
.expect("Invalid utf8 in error message")
}
}
}
impl Display for ErrorKind {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(self.determine_msg())
}
}