use alloc::string::String;
use core::fmt;
use core::panic::Location;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ErrorKind {
InvalidInput,
InvalidData,
InvalidState,
Unsupported,
#[doc(hidden)]
InsufficientBuffer,
}
pub struct Error {
pub kind: ErrorKind,
pub reason: String,
pub location: &'static Location<'static>,
}
impl Error {
#[track_caller]
pub fn new(kind: ErrorKind) -> Self {
Self::with_reason(kind, String::new())
}
#[track_caller]
pub fn with_reason<T: Into<String>>(kind: ErrorKind, reason: T) -> Self {
Self {
kind,
reason: reason.into(),
location: Location::caller(),
}
}
#[track_caller]
pub(crate) fn invalid_data<T: Into<String>>(reason: T) -> Self {
Self::with_reason(ErrorKind::InvalidData, reason)
}
#[track_caller]
pub(crate) fn invalid_input<T: Into<String>>(reason: T) -> Self {
Self::with_reason(ErrorKind::InvalidInput, reason)
}
#[track_caller]
pub(crate) fn invalid_state<T: Into<String>>(reason: T) -> Self {
Self::with_reason(ErrorKind::InvalidState, reason)
}
#[track_caller]
pub(crate) fn unsupported<T: Into<String>>(reason: T) -> Self {
Self::with_reason(ErrorKind::Unsupported, reason)
}
#[track_caller]
pub(crate) fn insufficient_buffer() -> Self {
Self::new(ErrorKind::InsufficientBuffer)
}
#[track_caller]
pub(crate) fn check_buffer_size(required_size: usize, buf: &[u8]) -> Result<(), Self> {
if buf.len() < required_size {
Err(Self::insufficient_buffer())
} else {
Ok(())
}
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self}")
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}: {}", self.kind, self.reason)?;
write!(f, " (at {}:{})", self.location.file(), self.location.line())?;
Ok(())
}
}
impl core::error::Error for Error {}