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