xsd_parser/schema/
occurs.rs

1use std::num::ParseIntError;
2use std::ops::{Add, Mul, MulAssign};
3use std::str::FromStr;
4use std::{cmp::Ordering, ops::AddAssign};
5
6use serde::{de::Error as DeError, Deserialize, Serialize};
7
8/// Represents the minimum occurrence of types or elements
9pub type MinOccurs = usize;
10
11/// Represents the maximum occurrence of types or elements
12#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
13pub enum MaxOccurs {
14    /// The occurrence is unbounded.
15    Unbounded,
16
17    /// The occurrence is bound to the specified limit.
18    Bounded(usize),
19}
20
21impl Add for MaxOccurs {
22    type Output = Self;
23
24    fn add(self, rhs: Self) -> Self::Output {
25        match (self, rhs) {
26            (Self::Bounded(a), Self::Bounded(b)) => Self::Bounded(a + b),
27            (_, _) => Self::Unbounded,
28        }
29    }
30}
31
32impl AddAssign for MaxOccurs {
33    fn add_assign(&mut self, rhs: Self) {
34        match (&mut *self, rhs) {
35            (Self::Bounded(a), Self::Bounded(b)) => *a += b,
36            (_, _) => *self = Self::Unbounded,
37        }
38    }
39}
40
41impl Mul for MaxOccurs {
42    type Output = Self;
43
44    fn mul(self, rhs: Self) -> Self::Output {
45        match (self, rhs) {
46            (Self::Bounded(a), Self::Bounded(b)) => Self::Bounded(a * b),
47            (_, _) => Self::Unbounded,
48        }
49    }
50}
51
52impl MulAssign for MaxOccurs {
53    fn mul_assign(&mut self, rhs: Self) {
54        match (&mut *self, rhs) {
55            (Self::Bounded(a), Self::Bounded(b)) => *a *= b,
56            (_, _) => *self = Self::Unbounded,
57        }
58    }
59}
60
61impl Ord for MaxOccurs {
62    fn cmp(&self, other: &Self) -> Ordering {
63        match (self, other) {
64            (Self::Bounded(a), Self::Bounded(b)) => a.cmp(b),
65            (Self::Unbounded, Self::Unbounded) => Ordering::Equal,
66            (Self::Bounded(_), Self::Unbounded) => Ordering::Less,
67            (Self::Unbounded, Self::Bounded(_)) => Ordering::Greater,
68        }
69    }
70}
71
72impl PartialOrd for MaxOccurs {
73    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
74        Some(Ord::cmp(self, other))
75    }
76}
77
78impl Default for MaxOccurs {
79    fn default() -> Self {
80        Self::Bounded(1)
81    }
82}
83
84impl FromStr for MaxOccurs {
85    type Err = ParseIntError;
86
87    fn from_str(s: &str) -> Result<Self, Self::Err> {
88        if s == "unbounded" {
89            Ok(Self::Unbounded)
90        } else {
91            Ok(Self::Bounded(usize::from_str(s)?))
92        }
93    }
94}
95
96impl Serialize for MaxOccurs {
97    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
98    where
99        S: serde::Serializer,
100    {
101        match self {
102            Self::Unbounded => serializer.serialize_str("unbounded"),
103            Self::Bounded(x) => serializer.serialize_str(&format!("{x}")),
104        }
105    }
106}
107
108impl<'de> Deserialize<'de> for MaxOccurs {
109    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
110    where
111        D: serde::Deserializer<'de>,
112    {
113        let s = String::deserialize(deserializer)?;
114        match s.as_str() {
115            "unbounded" => Ok(Self::Unbounded),
116            s => {
117                Ok(Self::Bounded(s.parse().map_err(|_| {
118                    DeError::custom("MaxOccurs. Invalid value!")
119                })?))
120            }
121        }
122    }
123}