xsd_types/lexical/
g_month.rs1use static_regular_grammar::RegularGrammar;
2
3use crate::lexical::parse_timezone;
4
5use super::{Lexical, LexicalFormOf};
6
7#[derive(RegularGrammar, PartialEq, Eq, PartialOrd, Ord, Hash)]
23#[grammar(sized(GMonthBuf, derive(PartialEq, Eq, PartialOrd, Ord, Hash)))]
24pub struct GMonth(str);
25
26impl GMonth {
27 pub fn parts(&self) -> Parts {
28 Parts {
29 month: &self.0[2..4],
30 timezone: if self.0.len() > 4 {
31 Some(&self.0[4..])
32 } else {
33 None
34 },
35 }
36 }
37}
38
39impl Lexical for GMonth {
40 type Error = InvalidGMonth<String>;
41
42 fn parse(value: &str) -> Result<&Self, Self::Error> {
43 Self::new(value).map_err(|_| InvalidGMonth(value.to_owned()))
44 }
45}
46
47impl LexicalFormOf<crate::GMonth> for GMonth {
48 type ValueError = std::convert::Infallible;
49
50 fn try_as_value(&self) -> Result<crate::GMonth, Self::ValueError> {
51 Ok(self.parts().to_g_month())
52 }
53}
54
55#[derive(Debug, PartialEq, Eq)]
56pub struct Parts<'a> {
57 pub month: &'a str,
58 pub timezone: Option<&'a str>,
59}
60
61impl<'a> Parts<'a> {
62 pub fn new(month: &'a str, timezone: Option<&'a str>) -> Self {
63 Self { month, timezone }
64 }
65
66 fn to_g_month(&self) -> crate::GMonth {
67 crate::GMonth::new(
68 self.month.parse().unwrap(),
69 self.timezone.map(parse_timezone),
70 )
71 .unwrap()
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn parsing() {
81 let vectors = [
82 ("--01", Parts::new("01", None)),
83 ("--02Z", Parts::new("02", Some("Z"))),
84 ("--03+05:00", Parts::new("03", Some("+05:00"))),
85 ];
86
87 for (input, parts) in vectors {
88 let lexical_repr = GMonth::new(input).unwrap();
89 assert_eq!(lexical_repr.parts(), parts);
90
91 let value = lexical_repr.try_as_value().unwrap();
92 assert_eq!(value.to_string().as_str(), input)
93 }
94 }
95}