scsys_core/errors/
error.rs

1/*
2   Appellation: error <mod>
3   Contrib: FL03 <jo3mccain@icloud.com>
4*/
5use super::kinds::*;
6use crate::id::AtomicId;
7#[cfg(feature = "alloc")]
8use alloc::string::{String, ToString};
9
10#[derive(Clone, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
11#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
12pub struct Error<K = String> {
13    id: AtomicId,
14    kind: Errors<K>,
15    message: String,
16}
17
18impl<K> Error<K> {
19    pub fn new(kind: impl Into<Errors<K>>, message: impl ToString) -> Self {
20        Self {
21            id: AtomicId::new(),
22            kind: kind.into(),
23            message: message.to_string(),
24        }
25    }
26
27    pub fn unknown(message: impl ToString) -> Self {
28        Self::new(Errors::<K>::unknown(), message.to_string())
29    }
30
31    pub fn id(&self) -> usize {
32        *self.id
33    }
34
35    pub fn kind(&self) -> &Errors<K> {
36        &self.kind
37    }
38
39    pub fn message(&self) -> &str {
40        &self.message
41    }
42
43    pub fn set_kind(&mut self, kind: Errors<K>) {
44        self.kind = kind;
45    }
46
47    pub fn set_message(&mut self, message: String) {
48        self.message = message;
49    }
50
51    pub fn with_kind(mut self, kind: Errors<K>) -> Self {
52        self.kind = kind;
53        self
54    }
55
56    pub fn with_message(mut self, message: String) -> Self {
57        self.message = message;
58        self
59    }
60}
61
62unsafe impl<K> Send for Error<K> {}
63
64unsafe impl<K> Sync for Error<K> {}
65
66impl<K> core::fmt::Debug for Error<K> {
67    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
68        write!(
69            f,
70            "[{kind}]: {msg}",
71            kind = self.kind(),
72            msg = self.message()
73        )
74    }
75}
76
77impl<K> core::fmt::Display for Error<K> {
78    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
79        write!(
80            f,
81            "[{kind}]: {msg}",
82            kind = self.kind(),
83            msg = self.message()
84        )
85    }
86}
87
88impl<K> core::error::Error for Error<K> {}
89
90#[cfg(feature = "alloc")]
91impl<K> From<Errors<K>> for Error<K> {
92    fn from(kind: Errors<K>) -> Self {
93        Self::new(kind, String::new())
94    }
95}
96
97macro_rules! impl_error_from {
98    ($variant:ident: $($from:ty),*) => {
99        $(
100            impl_error_from!(@impl $variant: $from);
101        )*
102    };
103    ($variant:ident<$n:path>.($($from:ty),*)) => {
104        $(impl_error_from!(@impl $variant<$n>: $from);)*
105    };
106    ($variant:ident($($n:ident)::*): $($from:ty),*) => {
107        $(
108            impl_error_from!(@impl $variant($($n)::*): $from);
109        )*
110    };
111    (@impl $variant:ident($($n:ident)::*): $from:ty) => {
112        impl<K> From<$from> for Error<K> {
113            fn from(err: $from) -> Self {
114                Self::new(Errors::$variant($($n)::*(err.into())), err.to_string())
115            }
116        }
117    };
118    (@impl $variant:ident<$n:path>: $from:ty) => {
119        impl<K> From<$from> for Error<K> {
120            fn from(err: $from) -> Self {
121                Self::new(Errors::$variant($n), err.to_string())
122            }
123        }
124    };
125    (@impl $variant:ident: $from:ty) => {
126        impl<K> From<$from> for Error<K> {
127            fn from(err: $from) -> Self {
128                Self::new(Errors::$variant, err.to_string())
129            }
130        }
131    };
132
133}
134
135impl_error_from!(Error<ExternalError::Unknown>.(String, &str));
136impl_error_from!(Parse: core::num::ParseFloatError, core::num::ParseIntError, core::str::Utf8Error);
137
138#[cfg(feature = "std")]
139impl_error_from!(Error<ExternalError::Unknown>.(Box<dyn std::error::Error>));
140#[cfg(feature = "std")]
141impl_error_from!(IO: std::io::Error);
142#[cfg(feature = "std")]
143impl_error_from!(Parse: std::string::FromUtf8Error, std::string::FromUtf16Error);