1 use std::fmt;
2 
3 /// An error encountered while working with structured data.
4 #[derive(Debug)]
5 pub struct Error {
6     inner: Inner,
7 }
8 
9 #[derive(Debug)]
10 enum Inner {
11     #[cfg(feature = "std")]
12     Boxed(std_support::BoxedError),
13     Msg(&'static str),
14     #[cfg(feature = "value-bag")]
15     Value(crate::kv::value::inner::Error),
16     Fmt,
17 }
18 
19 impl Error {
20     /// Create an error from a message.
msg(msg: &'static str) -> Self21     pub fn msg(msg: &'static str) -> Self {
22         Error {
23             inner: Inner::Msg(msg),
24         }
25     }
26 
27     // Not public so we don't leak the `crate::kv::value::inner` API
28     #[cfg(feature = "value-bag")]
from_value(err: crate::kv::value::inner::Error) -> Self29     pub(super) fn from_value(err: crate::kv::value::inner::Error) -> Self {
30         Error {
31             inner: Inner::Value(err),
32         }
33     }
34 
35     // Not public so we don't leak the `crate::kv::value::inner` API
36     #[cfg(feature = "value-bag")]
into_value(self) -> crate::kv::value::inner::Error37     pub(super) fn into_value(self) -> crate::kv::value::inner::Error {
38         match self.inner {
39             Inner::Value(err) => err,
40             #[cfg(feature = "kv_std")]
41             _ => crate::kv::value::inner::Error::boxed(self),
42             #[cfg(not(feature = "kv_std"))]
43             _ => crate::kv::value::inner::Error::msg("error inspecting a value"),
44         }
45     }
46 }
47 
48 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result49     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
50         use self::Inner::*;
51         match &self.inner {
52             #[cfg(feature = "std")]
53             Boxed(err) => err.fmt(f),
54             #[cfg(feature = "value-bag")]
55             Value(err) => err.fmt(f),
56             Msg(msg) => msg.fmt(f),
57             Fmt => fmt::Error.fmt(f),
58         }
59     }
60 }
61 
62 impl From<fmt::Error> for Error {
from(_: fmt::Error) -> Self63     fn from(_: fmt::Error) -> Self {
64         Error { inner: Inner::Fmt }
65     }
66 }
67 
68 #[cfg(feature = "std")]
69 mod std_support {
70     use super::*;
71     use std::{error, io};
72 
73     pub(super) type BoxedError = Box<dyn error::Error + Send + Sync>;
74 
75     impl Error {
76         /// Create an error from a standard error type.
boxed<E>(err: E) -> Self where E: Into<BoxedError>,77         pub fn boxed<E>(err: E) -> Self
78         where
79             E: Into<BoxedError>,
80         {
81             Error {
82                 inner: Inner::Boxed(err.into()),
83             }
84         }
85     }
86 
87     impl error::Error for Error {}
88 
89     impl From<io::Error> for Error {
from(err: io::Error) -> Self90         fn from(err: io::Error) -> Self {
91             Error::boxed(err)
92         }
93     }
94 }
95