xsd_parser/schema/
occurs.rs

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