1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

use crate::fields;
use displaydoc::Display;

/// These strings follow the recommendations for the serde::de::Unexpected::Other type.
/// <https://docs.serde.rs/serde/de/enum.Unexpected.html#variant.Other>
///
/// Serde will generate an error such as:
/// "invalid value: unclosed literal in pattern, expected a valid UTS 35 pattern string at line 1 column 12"
#[derive(Display, Debug, Copy, Clone, PartialEq)]
#[non_exhaustive]
pub enum SkeletonError {
    #[displaydoc("field too long in skeleton")]
    InvalidFieldLength,
    #[displaydoc("duplicate field in skeleton")]
    DuplicateField,
    #[displaydoc("symbol unknown {0} in skeleton")]
    SymbolUnknown(char),
    #[displaydoc("symbol invalid {0} in skeleton")]
    SymbolInvalid(u8),
    #[displaydoc("symbol unimplemented {0} in skeleton")]
    SymbolUnimplemented(char),
    #[displaydoc("unimplemented field {0} in skeleton")]
    UnimplementedField(char),
    #[displaydoc("skeleton has a variant subtag")]
    SkeletonHasVariant,
    #[displaydoc("{0}")]
    Fields(fields::Error),
}

#[cfg(feature = "std")]
impl std::error::Error for SkeletonError {}

#[cfg(feature = "experimental")]
impl From<SkeletonError> for crate::DateTimeError {
    fn from(e: SkeletonError) -> Self {
        crate::DateTimeError::Skeleton(e)
    }
}

impl From<fields::Error> for SkeletonError {
    fn from(e: fields::Error) -> Self {
        SkeletonError::Fields(e)
    }
}

impl From<fields::LengthError> for SkeletonError {
    fn from(_: fields::LengthError) -> Self {
        Self::InvalidFieldLength
    }
}

impl From<fields::SymbolError> for SkeletonError {
    fn from(symbol_error: fields::SymbolError) -> Self {
        match symbol_error {
            fields::SymbolError::Invalid(ch) => match ch {
                b'-' => Self::SkeletonHasVariant,
                _ => Self::SymbolInvalid(ch),
            },
            fields::SymbolError::InvalidIndex(_) => unimplemented!(),
            fields::SymbolError::Unknown(ch) => {
                // NOTE: If you remove a symbol due to it now being supported,
                //       make sure to regenerate data: cargo make bakeddata components/datetime.
                match ch {
                    // TODO(#487) - Flexible day periods
                    'B'
                    // TODO(#501) - Quarters
                    | 'Q'
                    => Self::SymbolUnimplemented(ch),
                    _ => Self::SymbolUnknown(ch),
                }
            }
        }
    }
}