tz/error/
mod.rs

1//! Error types.
2
3use core::array::TryFromSliceError;
4use core::fmt;
5use core::num::TryFromIntError;
6use core::str::Utf8Error;
7
8#[cfg(feature = "std")]
9mod parse {
10    use super::*;
11
12    use core::num::ParseIntError;
13
14    /// Unified error type for parsing a TZ string
15    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
16    #[non_exhaustive]
17    #[derive(Debug)]
18    pub enum TzStringError {
19        /// UTF-8 error
20        Utf8Error(Utf8Error),
21        /// Integer parsing error
22        ParseIntError(ParseIntError),
23        /// I/O error
24        IoError(std::io::Error),
25        /// Invalid TZ string
26        InvalidTzString(&'static str),
27        /// Unsupported TZ string
28        UnsupportedTzString(&'static str),
29    }
30
31    impl fmt::Display for TzStringError {
32        fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
33            match self {
34                Self::Utf8Error(error) => error.fmt(f),
35                Self::ParseIntError(error) => error.fmt(f),
36                Self::IoError(error) => error.fmt(f),
37                Self::InvalidTzString(error) => write!(f, "invalid TZ string: {}", error),
38                Self::UnsupportedTzString(error) => write!(f, "unsupported TZ string: {}", error),
39            }
40        }
41    }
42
43    impl std::error::Error for TzStringError {}
44
45    impl From<Utf8Error> for TzStringError {
46        fn from(error: Utf8Error) -> Self {
47            Self::Utf8Error(error)
48        }
49    }
50
51    impl From<ParseIntError> for TzStringError {
52        fn from(error: ParseIntError) -> Self {
53            Self::ParseIntError(error)
54        }
55    }
56
57    impl From<std::io::Error> for TzStringError {
58        fn from(error: std::io::Error) -> Self {
59            Self::IoError(error)
60        }
61    }
62
63    /// Unified error type for parsing a TZif file
64    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
65    #[non_exhaustive]
66    #[derive(Debug)]
67    pub enum TzFileError {
68        /// Conversion from slice to array error
69        TryFromSliceError(TryFromSliceError),
70        /// I/O error
71        IoError(std::io::Error),
72        /// Unified error for parsing a TZ string
73        TzStringError(TzStringError),
74        /// Invalid TZif file
75        InvalidTzFile(&'static str),
76        /// Unsupported TZif file
77        UnsupportedTzFile(&'static str),
78    }
79
80    impl fmt::Display for TzFileError {
81        fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
82            match self {
83                Self::TryFromSliceError(error) => error.fmt(f),
84                Self::IoError(error) => error.fmt(f),
85                Self::TzStringError(error) => error.fmt(f),
86                Self::InvalidTzFile(error) => write!(f, "invalid TZ file: {}", error),
87                Self::UnsupportedTzFile(error) => write!(f, "unsupported TZ file: {}", error),
88            }
89        }
90    }
91
92    impl std::error::Error for TzFileError {}
93
94    impl From<TryFromSliceError> for TzFileError {
95        fn from(error: TryFromSliceError) -> Self {
96            Self::TryFromSliceError(error)
97        }
98    }
99
100    impl From<std::io::Error> for TzFileError {
101        fn from(error: std::io::Error) -> Self {
102            Self::IoError(error)
103        }
104    }
105
106    impl From<TzStringError> for TzFileError {
107        fn from(error: TzStringError) -> Self {
108            Self::TzStringError(error)
109        }
110    }
111}
112
113#[cfg(feature = "std")]
114pub use parse::{TzFileError, TzStringError};
115
116macro_rules! create_error {
117    (#[$doc:meta], $name:ident) => {
118        #[$doc]
119        #[derive(Debug)]
120        pub struct $name(
121            /// Error description
122            pub &'static str,
123        );
124
125        impl fmt::Display for $name {
126            fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
127                self.0.fmt(f)
128            }
129        }
130
131        #[cfg(feature = "std")]
132        #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
133        impl std::error::Error for $name {}
134    };
135}
136
137create_error!(#[doc = "Out of range error"], OutOfRangeError);
138create_error!(#[doc = "Local time type error"], LocalTimeTypeError);
139create_error!(#[doc = "Transition rule error"], TransitionRuleError);
140create_error!(#[doc = "Time zone error"], TimeZoneError);
141create_error!(#[doc = "Date time error"], DateTimeError);
142create_error!(#[doc = "Local time type search error"], FindLocalTimeTypeError);
143create_error!(#[doc = "Date time projection error"], ProjectDateTimeError);
144
145impl From<OutOfRangeError> for ProjectDateTimeError {
146    fn from(error: OutOfRangeError) -> Self {
147        Self(error.0)
148    }
149}
150
151impl From<FindLocalTimeTypeError> for ProjectDateTimeError {
152    fn from(error: FindLocalTimeTypeError) -> Self {
153        Self(error.0)
154    }
155}
156
157/// Unified error type for everything in the crate
158#[non_exhaustive]
159#[derive(Debug)]
160pub enum TzError {
161    /// UTF-8 error
162    Utf8Error(Utf8Error),
163    /// Conversion from slice to array error
164    TryFromSliceError(TryFromSliceError),
165    /// I/O error
166    #[cfg(feature = "std")]
167    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
168    IoError(std::io::Error),
169    /// System time error
170    #[cfg(feature = "std")]
171    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
172    SystemTimeError(std::time::SystemTimeError),
173    /// Unified error for parsing a TZif file
174    #[cfg(feature = "std")]
175    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
176    TzFileError(TzFileError),
177    /// Unified error for parsing a TZ string
178    #[cfg(feature = "std")]
179    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
180    TzStringError(TzStringError),
181    /// Out of range error
182    OutOfRangeError(OutOfRangeError),
183    /// Local time type error
184    LocalTimeTypeError(LocalTimeTypeError),
185    /// Transition rule error
186    TransitionRuleError(TransitionRuleError),
187    /// Time zone error
188    TimeZoneError(TimeZoneError),
189    /// Date time error
190    DateTimeError(DateTimeError),
191    /// Local time type search error
192    FindLocalTimeTypeError(FindLocalTimeTypeError),
193    /// Date time projection error
194    ProjectDateTimeError(ProjectDateTimeError),
195}
196
197impl fmt::Display for TzError {
198    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
199        match self {
200            Self::Utf8Error(error) => error.fmt(f),
201            Self::TryFromSliceError(error) => error.fmt(f),
202            #[cfg(feature = "std")]
203            Self::IoError(error) => error.fmt(f),
204            #[cfg(feature = "std")]
205            Self::SystemTimeError(error) => error.fmt(f),
206            #[cfg(feature = "std")]
207            Self::TzFileError(error) => error.fmt(f),
208            #[cfg(feature = "std")]
209            Self::TzStringError(error) => error.fmt(f),
210            Self::OutOfRangeError(error) => error.fmt(f),
211            Self::LocalTimeTypeError(error) => write!(f, "invalid local time type: {}", error),
212            Self::TransitionRuleError(error) => write!(f, "invalid transition rule: {}", error),
213            Self::TimeZoneError(error) => write!(f, "invalid time zone: {}", error),
214            Self::DateTimeError(error) => write!(f, "invalid date time: {}", error),
215            Self::FindLocalTimeTypeError(error) => error.fmt(f),
216            Self::ProjectDateTimeError(error) => error.fmt(f),
217        }
218    }
219}
220
221#[cfg(feature = "std")]
222#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
223impl std::error::Error for TzError {}
224
225impl From<Utf8Error> for TzError {
226    fn from(error: Utf8Error) -> Self {
227        Self::Utf8Error(error)
228    }
229}
230
231impl From<TryFromSliceError> for TzError {
232    fn from(error: TryFromSliceError) -> Self {
233        Self::TryFromSliceError(error)
234    }
235}
236
237#[cfg(feature = "std")]
238#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
239impl From<std::io::Error> for TzError {
240    fn from(error: std::io::Error) -> Self {
241        Self::IoError(error)
242    }
243}
244
245#[cfg(feature = "std")]
246#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
247impl From<std::time::SystemTimeError> for TzError {
248    fn from(error: std::time::SystemTimeError) -> Self {
249        Self::SystemTimeError(error)
250    }
251}
252
253#[cfg(feature = "std")]
254#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
255impl From<TzFileError> for TzError {
256    fn from(error: TzFileError) -> Self {
257        Self::TzFileError(error)
258    }
259}
260
261#[cfg(feature = "std")]
262#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
263impl From<TzStringError> for TzError {
264    fn from(error: TzStringError) -> Self {
265        Self::TzStringError(error)
266    }
267}
268
269impl From<OutOfRangeError> for TzError {
270    fn from(error: OutOfRangeError) -> Self {
271        Self::OutOfRangeError(error)
272    }
273}
274
275impl From<TryFromIntError> for TzError {
276    fn from(_: TryFromIntError) -> Self {
277        Self::OutOfRangeError(OutOfRangeError("out of range integer conversion"))
278    }
279}
280
281impl From<LocalTimeTypeError> for TzError {
282    fn from(error: LocalTimeTypeError) -> Self {
283        Self::LocalTimeTypeError(error)
284    }
285}
286
287impl From<TransitionRuleError> for TzError {
288    fn from(error: TransitionRuleError) -> Self {
289        Self::TransitionRuleError(error)
290    }
291}
292
293impl From<TimeZoneError> for TzError {
294    fn from(error: TimeZoneError) -> Self {
295        Self::TimeZoneError(error)
296    }
297}
298
299impl From<DateTimeError> for TzError {
300    fn from(error: DateTimeError) -> Self {
301        Self::DateTimeError(error)
302    }
303}
304
305impl From<FindLocalTimeTypeError> for TzError {
306    fn from(error: FindLocalTimeTypeError) -> Self {
307        Self::FindLocalTimeTypeError(error)
308    }
309}
310
311impl From<ProjectDateTimeError> for TzError {
312    fn from(error: ProjectDateTimeError) -> Self {
313        Self::ProjectDateTimeError(error)
314    }
315}