use core::fmt;
use alloc::boxed::Box;
pub mod field;
pub use self::field::Field;
pub struct Error {
inner: Repr,
pub field: Field,
}
enum Repr {
Collision,
Other(Box<dyn core::error::Error + Send + Sync + 'static>),
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
struct Kind<'a>(&'a Repr);
impl fmt::Debug for Kind<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
Repr::Collision => write!(f, "Collision"),
Repr::Other(x) => f.debug_tuple("Other").field(&x).finish(),
}
}
}
f.debug_struct("Error")
.field("kind", &Kind(&self.inner))
.field("field", &self.field)
.finish()
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.field.is_empty() {
write!(f, "{:?}: ", self.field)?;
}
match self.inner {
Repr::Collision => write!(f, "value collision"),
Repr::Other(ref x) => {
if f.alternate() {
write!(f, "other error")
} else {
write!(f, "{x}")
}
}
}
}
}
impl core::error::Error for Error {
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
match self.inner {
Repr::Collision => None,
Repr::Other(ref x) => Some(&**x),
}
}
}
impl Error {
#[must_use]
pub const fn collision() -> Self {
Self::with_inner(Repr::Collision)
}
#[must_use]
pub fn other<E>(error: E) -> Self
where
E: core::error::Error + Send + Sync + 'static,
{
Self::with_inner(Repr::Other(Box::new(error)))
}
const fn with_inner(kind: Repr) -> Self {
Self {
inner: kind,
field: Field::empty(),
}
}
pub fn message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.inner {
Repr::Collision => write!(f, "value collision"),
Repr::Other(ref x) => write!(f, "{x:#}"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ErrorKind {
Collision,
Other,
}
impl Error {
#[must_use]
pub fn kind(&self) -> ErrorKind {
match self.inner {
Repr::Collision => ErrorKind::Collision,
Repr::Other(_) => ErrorKind::Other,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<Error>();
}
}