one_err/
one_err.rs

1use super::*;
2
3const ERROR: &str = "error";
4const OS: &str = "os";
5const SOURCE: &str = "source";
6const BACKTRACE: &str = "backtrace";
7const MESSAGE: &str = "message";
8
9/// OneErr to rule them all. See crate docs for usage.
10pub struct OneErr(std::io::Error);
11
12impl std::fmt::Display for OneErr {
13    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14        fmt_display(f, self)
15    }
16}
17
18impl std::fmt::Debug for OneErr {
19    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20        if f.alternate() {
21            fmt_debug_alt(f, self)
22        } else {
23            fmt_display(f, self)
24        }
25    }
26}
27
28impl std::error::Error for OneErr {}
29
30impl Clone for OneErr {
31    fn clone(&self) -> Self {
32        let k = self.0.kind();
33        Self(std::io::Error::new(k, self.priv_as_inner().clone()))
34    }
35}
36
37impl PartialEq for OneErr {
38    fn eq(&self, oth: &Self) -> bool {
39        if self.str_kind() != oth.str_kind() {
40            return false;
41        }
42        self.priv_as_inner() == oth.priv_as_inner()
43    }
44}
45
46impl Eq for OneErr {}
47
48impl From<std::io::ErrorKind> for OneErr {
49    fn from(k: std::io::ErrorKind) -> Self {
50        Self(std::io::Error::new(k, OneErrInner::new()))
51    }
52}
53
54impl From<i32> for OneErr {
55    fn from(e: i32) -> Self {
56        ErrNo::from(e).into()
57    }
58}
59
60impl From<ErrNo> for OneErr {
61    fn from(e: ErrNo) -> Self {
62        let k: std::io::ErrorKind = (&e).into();
63
64        let mut inner = OneErrInner::new();
65        if let std::io::ErrorKind::Other = k {
66            if let ErrNo::Other = e {
67                /* pass */
68            } else {
69                inner.set_field(OS.into(), i32::from(&e) as i64);
70            }
71        }
72
73        Self(std::io::Error::new(k, inner))
74    }
75}
76
77impl From<std::io::Error> for OneErr {
78    fn from(e: std::io::Error) -> Self {
79        // we have to be careful about this one...
80        // we need the inner to be a OneErrInner.
81
82        // if our inner data is already a OneErrorInner,
83        // we can just wrap it up, call it good.
84        if let Some(r) = e.get_ref() {
85            if r.downcast_ref::<OneErrInner>().is_some() {
86                return Self(e);
87            }
88        }
89
90        // if there is an os errno, use that
91        if let Some(e) = e.raw_os_error() {
92            return e.into();
93        }
94
95        // otherwise, just go off the io::ErrorKind
96        let message = format!("{}", e);
97        let mut inner = OneErrInner::new();
98        inner.set_field(MESSAGE.into(), message);
99        Self(std::io::Error::new(e.kind(), inner))
100    }
101}
102
103impl From<()> for OneErr {
104    fn from(_: ()) -> Self {
105        std::io::ErrorKind::Other.into()
106    }
107}
108
109impl From<String> for OneErr {
110    fn from(s: String) -> Self {
111        s.as_str().into()
112    }
113}
114
115impl From<&String> for OneErr {
116    fn from(s: &String) -> Self {
117        s.as_str().into()
118    }
119}
120
121impl From<&str> for OneErr {
122    fn from(s: &str) -> Self {
123        OneErr::new(s)
124    }
125}
126
127impl From<OneErr> for std::io::Error {
128    fn from(e: OneErr) -> Self {
129        e.0
130    }
131}
132
133impl From<&OneErr> for std::io::Error {
134    fn from(e: &OneErr) -> Self {
135        e.clone().0
136    }
137}
138
139impl std::ops::Deref for OneErr {
140    type Target = std::io::Error;
141
142    fn deref(&self) -> &Self::Target {
143        &self.0
144    }
145}
146
147impl AsRef<std::io::Error> for OneErr {
148    fn as_ref(&self) -> &std::io::Error {
149        &self.0
150    }
151}
152
153impl serde::Serialize for OneErr {
154    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
155    where
156        S: serde::Serializer,
157    {
158        use serde::ser::SerializeMap;
159
160        let (kind, os, inner) = self.priv_as_parts();
161        let error: &str = if let Some(os) = os {
162            if let ErrNo::Other = os {
163                if let Some(f) = &*inner.0 {
164                    if let Some(e_str) = f.get(ERROR) {
165                        if let Some(e_str) = e_str.as_str() {
166                            e_str
167                        } else {
168                            <&'static str>::from(os)
169                        }
170                    } else {
171                        <&'static str>::from(os)
172                    }
173                } else {
174                    <&'static str>::from(os)
175                }
176            } else {
177                <&'static str>::from(os)
178            }
179        } else {
180            if let std::io::ErrorKind::Other = kind {
181                if let Some(f) = &*inner.0 {
182                    if let Some(e_str) = f.get(ERROR) {
183                        if let Some(e_str) = e_str.as_str() {
184                            e_str
185                        } else {
186                            err_kind_to_str(kind)
187                        }
188                    } else {
189                        err_kind_to_str(kind)
190                    }
191                } else {
192                    err_kind_to_str(kind)
193                }
194            } else {
195                err_kind_to_str(kind)
196            }
197        };
198
199        let mut count = 1;
200        if let Some(f) = &*inner.0 {
201            count += f.len();
202
203            if f.contains_key(ERROR) {
204                count -= 1;
205            }
206
207            if f.contains_key(OS) {
208                count -= 1;
209            }
210        }
211
212        let mut map = serializer.serialize_map(Some(count))?;
213
214        map.serialize_entry(ERROR, &error)?;
215
216        if let Some(f) = &*inner.0 {
217            for (n, v) in f.iter() {
218                match &**n {
219                    ERROR | OS => continue,
220                    _ => map.serialize_entry(n, v)?,
221                }
222            }
223        }
224
225        map.end()
226    }
227}
228
229impl<'de> serde::Deserialize<'de> for OneErr {
230    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
231    where
232        D: serde::Deserializer<'de>,
233    {
234        struct V;
235        impl<'de> serde::de::Visitor<'de> for V {
236            type Value = TopMap;
237
238            fn expecting(
239                &self,
240                f: &mut std::fmt::Formatter<'_>,
241            ) -> std::fmt::Result {
242                f.write_str("OneErr Map")
243            }
244
245            fn visit_map<A>(
246                self,
247                mut access: A,
248            ) -> Result<Self::Value, A::Error>
249            where
250                A: serde::de::MapAccess<'de>,
251            {
252                let mut out_map = TopMap::new();
253                loop {
254                    let r: Option<(Box<str>, Value)> = access.next_entry()?;
255                    match r {
256                        None => break,
257                        Some((k, v)) => {
258                            out_map.insert(k, v);
259                        }
260                    }
261                }
262                Ok(out_map)
263            }
264        }
265        let mut top_map: TopMap = deserializer.deserialize_map(V)?;
266        if let Some(error) = top_map.remove(ERROR) {
267            if let Some(error) = error.as_str() {
268                let (kind, os) = parse_err_str(error);
269                if let Some(os) = os {
270                    if let std::io::ErrorKind::Other = kind {
271                        top_map
272                            .insert(OS.into(), (i32::from(&os) as i64).into());
273                    }
274                } else {
275                    if let std::io::ErrorKind::Other = kind {
276                        if error != "Other" && error != "EOTHER" {
277                            top_map.insert(ERROR.into(), error.into());
278                        }
279                    }
280                }
281                if top_map.is_empty() {
282                    Ok(Self(std::io::Error::new(kind, OneErrInner::new())))
283                } else {
284                    Ok(Self(std::io::Error::new(
285                        kind,
286                        OneErrInner(Box::new(Some(top_map))),
287                    )))
288                }
289            } else {
290                Err(serde::de::Error::custom("required 'error' field is a str"))
291            }
292        } else {
293            Err(serde::de::Error::custom("required 'error' field"))
294        }
295    }
296}
297
298impl std::str::FromStr for OneErr {
299    type Err = OneErr;
300
301    fn from_str(s: &str) -> Result<Self, Self::Err> {
302        serde_json::from_str(s).map_err(|e| {
303            OneErr::with_message(crate::io_error::INVALID_DATA_STR, &e)
304        })
305    }
306}
307
308impl OneErr {
309    /// Create a new OneErr error instance.
310    pub fn new<K>(kind: K) -> Self
311    where
312        K: std::fmt::Display,
313    {
314        let kind_str = kind.to_string();
315        let (kind, os) = parse_err_str(&kind_str);
316        if let Some(os) = os {
317            if let ErrNo::Other = os {
318                let mut inner = OneErrInner::new();
319                inner.set_field(ERROR.into(), kind_str);
320
321                Self(std::io::Error::new(kind, inner))
322            } else {
323                os.into()
324            }
325        } else {
326            if let std::io::ErrorKind::Other = kind {
327                let mut inner = OneErrInner::new();
328                inner.set_field(ERROR.into(), kind_str);
329
330                Self(std::io::Error::new(kind, inner))
331            } else {
332                kind.into()
333            }
334        }
335    }
336
337    /// Create a new OneErr error instance with a message.
338    pub fn with_message<K, M>(kind: K, message: M) -> Self
339    where
340        K: std::fmt::Display,
341        M: std::fmt::Display,
342    {
343        let mut err = Self::new(kind);
344        err.priv_as_inner_mut()
345            .set_field(MESSAGE.into(), message.to_string());
346        err
347    }
348
349    /// Get the std::io::ErrorKind associated with this instance.
350    pub fn io_kind(&self) -> std::io::ErrorKind {
351        self.0.kind()
352    }
353
354    /// Get the ErrNo associated with this instance, if any.
355    pub fn errno(&self) -> ErrNo {
356        let inner = self.priv_as_inner();
357
358        if let Some(os) = inner.get_field::<i64>(OS) {
359            return ErrNo::from(os as i32);
360        }
361
362        ErrNo::from(self.0.kind())
363    }
364
365    /// Get the &str kind associated with this instance.
366    /// This can be more descriptive where `io_kind()` or `errno()`
367    /// might return 'Other'.
368    pub fn str_kind(&self) -> &str {
369        let inner = self.priv_as_inner();
370
371        if let Some(e_str) = inner.get_field::<&str>(ERROR) {
372            return e_str;
373        }
374
375        if let Some(os) = inner.get_field::<i64>(OS) {
376            let os = ErrNo::from(os as i32);
377            return <&'static str>::from(os);
378        }
379
380        err_kind_to_str(self.0.kind())
381    }
382
383    /// Get a reference to the inner std::io::Error of this instance.
384    pub fn as_io(&self) -> &std::io::Error {
385        self.as_ref()
386    }
387
388    /// Set an additional data field on this OneErr.
389    /// Will panic on reserved names: "error", "os", "source",
390    /// "backtrace", "message".
391    pub fn set_field<K, T>(&mut self, name: &K, t: T) -> &mut Self
392    where
393        K: ?Sized + std::fmt::Display,
394        T: Into<Value>,
395    {
396        let name = name.to_string().into_boxed_str();
397        match &*name {
398            ERROR | OS | SOURCE | BACKTRACE | MESSAGE => {
399                panic!("field name '{}' is reserved", name)
400            }
401            _ => (),
402        }
403
404        self.priv_as_inner_mut().set_field(name, t);
405        self
406    }
407
408    /// Get the message associated with this instance, or empty string.
409    pub fn get_message(&self) -> Option<&str> {
410        self.get_field(MESSAGE)
411    }
412
413    /// Get the value of an additional field associated with
414    /// this error, or None if no such field exists. Valid output types:
415    /// `&str`, `bool`, `i64`, `u64`, and `f64`.
416    pub fn get_field<'lt, R, V>(&'lt self, name: R) -> Option<V>
417    where
418        R: AsRef<str>,
419        Option<V>: From<&'lt Value>,
420    {
421        self.priv_as_inner().get_field(name.as_ref())
422    }
423}
424
425// -- private -- //
426
427impl OneErr {
428    pub(crate) fn priv_as_inner(&self) -> &OneErrInner {
429        // we can do all these unwraps because we control
430        // our inner type to always be valid and of OneErrInner type.
431        self.0
432            .get_ref()
433            .unwrap()
434            .downcast_ref::<OneErrInner>()
435            .unwrap()
436    }
437
438    pub(crate) fn priv_as_parts(
439        &self,
440    ) -> (std::io::ErrorKind, Option<ErrNo>, &OneErrInner) {
441        let kind = self.0.kind();
442        let inner = self.priv_as_inner();
443        let os = inner.get_field::<i64>(OS).map(|e| ErrNo::from(e as i32));
444        (kind, os, inner)
445    }
446
447    pub(crate) fn priv_as_inner_mut(&mut self) -> &mut OneErrInner {
448        // we can do all these unwraps because we control
449        // our inner type to always be valid and of OneErrInner type.
450        self.0
451            .get_mut()
452            .unwrap()
453            .downcast_mut::<OneErrInner>()
454            .unwrap()
455    }
456}