utf8proc 0.1.2

Rust bindings to the utf8proc library
Documentation
//! Defines the primary [`Error`] type for the crate.

use libc::ssize_t;
use num_enum::FromPrimitive;
use std::ffi::CStr;
use std::fmt::{Display, Formatter};
use utf8proc_sys::utf8proc_errmsg;

/// Indicates an error that occurred in utf8proc.
///
/// When possible, more specific error types will be used.
#[derive(Debug, Clone, thiserror::Error)]
#[error("{kind}")]
pub struct Error {
    kind: ErrorKind,
}

impl Error {
    /// Create an error from an [`ErrorKind`],
    /// without any additional information.
    #[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 {
    /// The kind of this error.
    #[inline]
    pub fn kind(&self) -> ErrorKind {
        self.kind
    }
}
impl From<ErrorKind> for Error {
    fn from(value: ErrorKind) -> Self {
        Error { kind: value }
    }
}
/// Indicates the type of the underlying [`utf8proc::Error`](Error).
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, FromPrimitive)]
#[repr(isize)]
#[non_exhaustive]
pub enum ErrorKind {
    /// Memory allocation failed.
    OutOfMemory = utf8proc_sys::UTF8PROC_ERROR_NOMEM,
    /// The string is too long to be processed.
    StringOverflow = utf8proc_sys::UTF8PROC_ERROR_OVERFLOW,
    /// The given string is not a legal UTF-8 string.
    InvalidUtf8 = utf8proc_sys::UTF8PROC_ERROR_INVALIDUTF8,
    /// The `UTF8PROC_REJECTNA` flag has been set and unassigned codepoint has been found.
    NotAssigned = utf8proc_sys::UTF8PROC_ERROR_NOTASSIGNED,
    /// Invalid options have been passed to a FFI function.
    ///
    /// The safe utf8proc.rs wrapper validates options
    /// before giving it to the underlying FFI function.
    /// So this error should generally not happen.
    /// It should instead be prevented by the type system
    /// or trigger a descriptive panic.
    InvalidOptions = utf8proc_sys::UTF8PROC_ERROR_INVALIDOPTS,
    /// An unknown type of error has occurred,
    /// not is not otherwise enumerated here.
    ///
    /// Only intended for use inside the library
    #[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 {
        // SAFETY: Result of utf8proc_errmsg is null-terminated constant string
        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())
    }
}