dos_date_time/error/
dos_date.rs

1// SPDX-FileCopyrightText: 2025 Shun Sakai
2//
3// SPDX-License-Identifier: Apache-2.0 OR MIT
4
5//! Error types for [`Date`](crate::Date).
6
7use core::{error::Error, fmt};
8
9/// The error type indicating that a [`Date`](crate::Date) was out of range.
10#[derive(Clone, Copy, Debug, Eq, PartialEq)]
11pub struct DateRangeError(DateRangeErrorKind);
12
13impl DateRangeError {
14    pub(crate) const fn new(kind: DateRangeErrorKind) -> Self {
15        Self(kind)
16    }
17
18    /// Returns the corresponding [`DateRangeErrorKind`] for this error.
19    ///
20    /// # Examples
21    ///
22    /// ```
23    /// # use dos_date_time::{Date, error::DateRangeErrorKind, time::macros::date};
24    /// #
25    /// let err = Date::from_date(date!(1979-12-31)).unwrap_err();
26    /// assert_eq!(err.kind(), DateRangeErrorKind::Negative);
27    ///
28    /// let err = Date::from_date(date!(2108-01-01)).unwrap_err();
29    /// assert_eq!(err.kind(), DateRangeErrorKind::Overflow);
30    /// ```
31    #[must_use]
32    pub const fn kind(&self) -> DateRangeErrorKind {
33        self.0
34    }
35}
36
37impl fmt::Display for DateRangeError {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        self.kind().fmt(f)
40    }
41}
42
43impl Error for DateRangeError {}
44
45impl From<DateRangeErrorKind> for DateRangeError {
46    fn from(kind: DateRangeErrorKind) -> Self {
47        Self::new(kind)
48    }
49}
50
51/// Details of the error that caused a [`DateRangeError`].
52#[derive(Clone, Copy, Debug, Eq, PartialEq)]
53pub enum DateRangeErrorKind {
54    /// Value was negative.
55    ///
56    /// This means the MS-DOS date was before "1980-01-01".
57    Negative,
58
59    /// Value was too big to be represented as [`Date`](crate::Date).
60    ///
61    /// This means the MS-DOS date was after "2107-12-31".
62    Overflow,
63}
64
65impl fmt::Display for DateRangeErrorKind {
66    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67        match self {
68            Self::Negative => write!(f, "MS-DOS date is before `1980-01-01`"),
69            Self::Overflow => write!(f, "MS-DOS date is after `2107-12-31`"),
70        }
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    #[test]
79    fn clone_date_range_error() {
80        assert_eq!(
81            DateRangeError::new(DateRangeErrorKind::Negative).clone(),
82            DateRangeError::new(DateRangeErrorKind::Negative)
83        );
84        assert_eq!(
85            DateRangeError::new(DateRangeErrorKind::Overflow).clone(),
86            DateRangeError::new(DateRangeErrorKind::Overflow)
87        );
88    }
89
90    #[test]
91    fn copy_date_range_error() {
92        {
93            let a = DateRangeError::new(DateRangeErrorKind::Negative);
94            let b = a;
95            assert_eq!(a, b);
96        }
97
98        {
99            let a = DateRangeError::new(DateRangeErrorKind::Overflow);
100            let b = a;
101            assert_eq!(a, b);
102        }
103    }
104
105    #[test]
106    fn debug_date_range_error() {
107        assert_eq!(
108            format!("{:?}", DateRangeError::new(DateRangeErrorKind::Negative)),
109            "DateRangeError(Negative)"
110        );
111        assert_eq!(
112            format!("{:?}", DateRangeError::new(DateRangeErrorKind::Overflow)),
113            "DateRangeError(Overflow)"
114        );
115    }
116
117    #[test]
118    fn date_range_error_equality() {
119        assert_eq!(
120            DateRangeError::new(DateRangeErrorKind::Negative),
121            DateRangeError::new(DateRangeErrorKind::Negative)
122        );
123        assert_ne!(
124            DateRangeError::new(DateRangeErrorKind::Negative),
125            DateRangeError::new(DateRangeErrorKind::Overflow)
126        );
127        assert_ne!(
128            DateRangeError::new(DateRangeErrorKind::Overflow),
129            DateRangeError::new(DateRangeErrorKind::Negative)
130        );
131        assert_eq!(
132            DateRangeError::new(DateRangeErrorKind::Overflow),
133            DateRangeError::new(DateRangeErrorKind::Overflow)
134        );
135    }
136
137    #[test]
138    fn kind_date_range_error() {
139        assert_eq!(
140            DateRangeError::new(DateRangeErrorKind::Negative).kind(),
141            DateRangeErrorKind::Negative
142        );
143        assert_eq!(
144            DateRangeError::new(DateRangeErrorKind::Overflow).kind(),
145            DateRangeErrorKind::Overflow
146        );
147    }
148
149    #[test]
150    const fn kind_date_range_error_is_const_fn() {
151        const _: DateRangeErrorKind = DateRangeError::new(DateRangeErrorKind::Negative).kind();
152    }
153
154    #[test]
155    fn display_date_range_error() {
156        assert_eq!(
157            format!("{}", DateRangeError::new(DateRangeErrorKind::Negative)),
158            "MS-DOS date is before `1980-01-01`"
159        );
160        assert_eq!(
161            format!("{}", DateRangeError::new(DateRangeErrorKind::Overflow)),
162            "MS-DOS date is after `2107-12-31`"
163        );
164    }
165
166    #[test]
167    fn source_date_range_error() {
168        assert!(
169            DateRangeError::new(DateRangeErrorKind::Negative)
170                .source()
171                .is_none()
172        );
173        assert!(
174            DateRangeError::new(DateRangeErrorKind::Overflow)
175                .source()
176                .is_none()
177        );
178    }
179
180    #[test]
181    fn from_date_range_error_kind_to_date_range_error() {
182        assert_eq!(
183            DateRangeError::from(DateRangeErrorKind::Negative),
184            DateRangeError::new(DateRangeErrorKind::Negative)
185        );
186        assert_eq!(
187            DateRangeError::from(DateRangeErrorKind::Overflow),
188            DateRangeError::new(DateRangeErrorKind::Overflow)
189        );
190    }
191
192    #[test]
193    fn clone_date_range_error_kind() {
194        assert_eq!(
195            DateRangeErrorKind::Negative.clone(),
196            DateRangeErrorKind::Negative
197        );
198        assert_eq!(
199            DateRangeErrorKind::Overflow.clone(),
200            DateRangeErrorKind::Overflow
201        );
202    }
203
204    #[test]
205    fn copy_date_range_error_kind() {
206        {
207            let a = DateRangeErrorKind::Negative;
208            let b = a;
209            assert_eq!(a, b);
210        }
211
212        {
213            let a = DateRangeErrorKind::Overflow;
214            let b = a;
215            assert_eq!(a, b);
216        }
217    }
218
219    #[test]
220    fn debug_date_range_error_kind() {
221        assert_eq!(format!("{:?}", DateRangeErrorKind::Negative), "Negative");
222        assert_eq!(format!("{:?}", DateRangeErrorKind::Overflow), "Overflow");
223    }
224
225    #[test]
226    fn date_range_error_kind_equality() {
227        assert_eq!(DateRangeErrorKind::Negative, DateRangeErrorKind::Negative);
228        assert_ne!(DateRangeErrorKind::Negative, DateRangeErrorKind::Overflow);
229        assert_ne!(DateRangeErrorKind::Overflow, DateRangeErrorKind::Negative);
230        assert_eq!(DateRangeErrorKind::Overflow, DateRangeErrorKind::Overflow);
231    }
232
233    #[test]
234    fn display_date_range_error_kind() {
235        assert_eq!(
236            format!("{}", DateRangeErrorKind::Negative),
237            "MS-DOS date is before `1980-01-01`"
238        );
239        assert_eq!(
240            format!("{}", DateRangeErrorKind::Overflow),
241            "MS-DOS date is after `2107-12-31`"
242        );
243    }
244}