icu_calendar/
error.rs

1// This file is part of ICU4X. For terms of use, please see the file
2// called LICENSE at the top level of the ICU4X source tree
3// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5use crate::types::MonthCode;
6use displaydoc::Display;
7
8#[derive(Debug, Copy, Clone, PartialEq, Display)]
9/// Error type for date creation.
10#[non_exhaustive]
11pub enum DateError {
12    /// A field is out of range for its domain.
13    #[displaydoc("The {field} = {value} argument is out of range {min}..={max}")]
14    Range {
15        /// The field that is out of range, such as "year"
16        field: &'static str,
17        /// The actual value
18        value: i32,
19        /// The minimum value (inclusive). This might not be tight.
20        min: i32,
21        /// The maximum value (inclusive). This might not be tight.
22        max: i32,
23    },
24    /// Unknown era
25    #[displaydoc("Unknown era")]
26    UnknownEra,
27    /// Unknown month code
28    #[displaydoc("Unknown month code {0:?}")]
29    UnknownMonthCode(MonthCode),
30}
31
32impl core::error::Error for DateError {}
33
34#[derive(Debug, Copy, Clone, PartialEq, Display)]
35/// An argument is out of range for its domain.
36#[displaydoc("The {field} = {value} argument is out of range {min}..={max}")]
37#[allow(clippy::exhaustive_structs)]
38pub struct RangeError {
39    /// The argument that is out of range, such as "year"
40    pub field: &'static str,
41    /// The actual value
42    pub value: i32,
43    /// The minimum value (inclusive). This might not be tight.
44    pub min: i32,
45    /// The maximum value (inclusive). This might not be tight.
46    pub max: i32,
47}
48
49impl core::error::Error for RangeError {}
50
51impl From<RangeError> for DateError {
52    fn from(value: RangeError) -> Self {
53        let RangeError {
54            field,
55            value,
56            min,
57            max,
58        } = value;
59        DateError::Range {
60            field,
61            value,
62            min,
63            max,
64        }
65    }
66}
67
68pub(crate) fn year_check(
69    year: i32,
70    bounds: impl core::ops::RangeBounds<i32>,
71) -> Result<i32, RangeError> {
72    use core::ops::Bound::*;
73
74    if !bounds.contains(&year) {
75        return Err(RangeError {
76            field: "year",
77            value: year,
78            min: match bounds.start_bound() {
79                Included(&m) => m,
80                Excluded(&m) => m + 1,
81                Unbounded => i32::MIN,
82            },
83            max: match bounds.end_bound() {
84                Included(&m) => m,
85                Excluded(&m) => m - 1,
86                Unbounded => i32::MAX,
87            },
88        });
89    }
90
91    Ok(year)
92}