1use parse_display::Display;
2use std::io;
3
4pub type Result<T> = std::result::Result<T, Error>;
8
9#[derive(Copy, Clone, Eq, PartialEq, Display, Debug)]
11pub enum ErrorKind {
12 #[display("unexpected EOF")]
14 EOF,
15
16 #[display("IO error")]
18 IO,
19
20 #[display("truncation failed")]
22 TruncationFailed,
23
24 #[display("unable to open file")]
26 OpenFailed,
27
28 #[display("unable to open dir")]
30 OpenDirFailed,
31
32 #[display("flush file failed")]
34 FlushFailed,
35
36 #[display("sync file failed")]
38 SyncFileFailed,
39
40 #[display("sync dir failed")]
42 SyncDirFailed,
43
44 #[display("mmap failed")]
46 MmapFailed,
47
48 #[display("remmap failed")]
50 RemmapFailed,
51
52 #[display("range start must not be greater than end: {0} <= {1}")]
54 InvalidBound(usize, usize),
55
56 #[display("range end out of bounds: {0} <= {1}")]
58 OutOfBound(usize, usize),
59
60 #[display("call on an empty mmap file")]
62 InvokeEmptyMmap,
63
64 #[cfg(not(feature = "nightly"))]
66 #[display("not a directory")]
67 NotADirectory,
68}
69
70enum Repr {
71 Simple(ErrorKind),
72 Message { kd: ErrorKind, msg: String },
73 Source(Box<Source>),
74 SourceMessage { msg: String, src: Box<Source> },
75}
76
77struct Source {
78 kind: ErrorKind,
79 error: Box<dyn std::error::Error + Send + Sync>,
80}
81
82pub struct Error {
84 repr: Repr,
85}
86
87impl Error {
88 pub(crate) fn new<E>(kd: ErrorKind, src: E) -> Self
89 where
90 E: Into<Box<dyn std::error::Error + Send + Sync>>,
91 {
92 Self::_new(kd, src.into())
93 }
94
95 fn _new(kind: ErrorKind, error: Box<dyn std::error::Error + Send + Sync>) -> Self {
96 Error {
97 repr: Repr::Source(Box::new(Source { kind, error })),
98 }
99 }
100
101 pub(crate) fn new_with_message<M>(kd: ErrorKind, msg: M) -> Self
102 where
103 M: Into<String>,
104 {
105 Self {
106 repr: Repr::Message {
107 kd,
108 msg: msg.into(),
109 },
110 }
111 }
112
113 pub(crate) fn new_source_msg<M, E>(kd: ErrorKind, msg: M, src: E) -> Self
114 where
115 E: Into<Box<dyn std::error::Error + Send + Sync>>,
116 M: Into<String>,
117 {
118 Self {
119 repr: Repr::SourceMessage {
120 msg: msg.into(),
121 src: Box::new(Source {
122 kind: kd,
123 error: src.into(),
124 }),
125 },
126 }
127 }
128
129 pub(crate) fn f(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 match &self.repr {
131 Repr::Simple(kd) => write!(formatter, "{}", kd),
132 Repr::Source(src) => write!(formatter, "{}: {}", src.error, src.kind),
133 Repr::Message { kd, msg } => write!(formatter, "{}: {}", msg, kd),
134 Repr::SourceMessage { msg, src } => {
135 write!(formatter, "{}: {}: {}", msg, src.kind, src.error)
136 }
137 }
138 }
139
140 pub fn kind(&self) -> ErrorKind {
144 match &self.repr {
145 Repr::Simple(kd) => *kd,
146 Repr::Message { kd, msg: _ } => *kd,
147 Repr::Source(src) => src.kind,
148 Repr::SourceMessage { msg: _, src } => src.kind,
149 }
150 }
151}
152
153impl From<ErrorKind> for Error {
154 fn from(kd: ErrorKind) -> Self {
155 Self {
156 repr: Repr::Simple(kd),
157 }
158 }
159}
160
161impl std::fmt::Debug for Error {
162 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
163 self.f(f)
164 }
165}
166
167impl std::fmt::Display for Error {
168 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
169 self.f(f)
170 }
171}
172
173impl std::error::Error for Error {
174 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
175 match self.repr {
176 Repr::Simple(_) => None,
177 Repr::Source(ref c) => Some(c.error.as_ref()),
178 Repr::Message { .. } => None,
179 Repr::SourceMessage { msg: _, ref src } => Some(src.error.as_ref()),
180 }
181 }
182}
183
184impl From<io::Error> for Error {
185 fn from(err: io::Error) -> Self {
186 match err.kind() {
187 io::ErrorKind::UnexpectedEof => Error::new(ErrorKind::EOF, err),
188 _ => Error::new(ErrorKind::IO, err),
189 }
190 }
191}