1use core::iter::Sum;
2use core::ops;
3
4use crate::{DynTagged, Error, InnerError, Result, Tag};
5
6#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
8pub enum Length {
9 Definite(usize),
11 Indefinite,
13}
14
15impl Length {
16 #[inline]
18 pub fn is_null(&self) -> bool {
19 *self == Length::Definite(0)
20 }
21
22 #[inline]
24 pub fn definite(&self) -> Result<usize> {
25 match self {
26 Length::Definite(sz) => Ok(*sz),
27 Length::Indefinite => Err(Error::IndefiniteLengthUnexpected),
28 }
29 }
30
31 #[inline]
33 pub fn definite_inner(&self) -> Result<usize, InnerError> {
34 match self {
35 Length::Definite(sz) => Ok(*sz),
36 Length::Indefinite => Err(InnerError::IndefiniteLengthUnexpected),
37 }
38 }
39
40 #[inline]
42 pub const fn is_definite(&self) -> bool {
43 matches!(self, Length::Definite(_))
44 }
45
46 #[inline]
48 pub const fn assert_definite(&self) -> Result<()> {
49 match self {
50 Length::Definite(_) => Ok(()),
51 Length::Indefinite => Err(Error::IndefiniteLengthUnexpected),
52 }
53 }
54
55 #[inline]
57 pub const fn assert_definite_inner(&self) -> Result<(), InnerError> {
58 match self {
59 Length::Definite(_) => Ok(()),
60 Length::Indefinite => Err(InnerError::IndefiniteLengthUnexpected),
61 }
62 }
63}
64
65impl From<usize> for Length {
66 fn from(l: usize) -> Self {
67 Length::Definite(l)
68 }
69}
70
71impl ops::Add<Length> for Length {
72 type Output = Self;
73
74 fn add(self, rhs: Length) -> Self::Output {
75 match self {
76 Length::Indefinite => self,
77 Length::Definite(lhs) => match rhs {
78 Length::Indefinite => rhs,
79 Length::Definite(rhs) => Length::Definite(lhs + rhs),
80 },
81 }
82 }
83}
84
85impl ops::AddAssign<Length> for Length {
86 fn add_assign(&mut self, rhs: Length) {
87 match (*self, rhs) {
88 (Length::Definite(lhs), Length::Definite(r)) => *self = Length::Definite(lhs + r),
89 (Length::Indefinite, _) => (),
90 (_, Length::Indefinite) => *self = rhs,
91 }
92 }
93}
94
95impl ops::Add<usize> for Length {
96 type Output = Self;
97
98 fn add(self, rhs: usize) -> Self::Output {
99 match self {
100 Length::Definite(lhs) => Length::Definite(lhs + rhs),
101 Length::Indefinite => self,
102 }
103 }
104}
105
106impl ops::Add<Length> for usize {
107 type Output = Length;
108
109 fn add(self, rhs: Length) -> Self::Output {
110 match rhs {
111 Length::Definite(l) => Length::Definite(self + l),
112 Length::Indefinite => rhs,
113 }
114 }
115}
116
117impl ops::AddAssign<usize> for Length {
118 fn add_assign(&mut self, rhs: usize) {
119 match self {
120 Length::Definite(ref mut lhs) => *lhs += rhs,
121 Length::Indefinite => (),
122 }
123 }
124}
125
126impl Sum<Length> for Length {
127 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
128 iter.fold(Length::Definite(0), |a, b| a + b)
129 }
130}
131
132impl<'a> Sum<&'a Length> for Length {
133 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
134 iter.fold(Length::Definite(0), |a, b| a + *b)
135 }
136}
137
138impl DynTagged for Length {
139 fn tag(&self) -> Tag {
140 Tag(0)
141 }
142
143 fn accept_tag(_: Tag) -> bool {
144 true
145 }
146}
147
148#[cfg(test)]
149mod tests {
150 use crate::*;
151
152 #[test]
154 fn methods_length() {
155 let l = Length::from(2);
156 assert_eq!(l.definite(), Ok(2));
157 assert!(l.assert_definite().is_ok());
158
159 let l = Length::Indefinite;
160 assert!(l.definite().is_err());
161 assert!(l.assert_definite().is_err());
162
163 let l = Length::from(2);
164 assert_eq!(l + 2, Length::from(4));
165 assert_eq!(l + Length::Indefinite, Length::Indefinite);
166
167 let l = Length::Indefinite;
168 assert_eq!(l + 2, Length::Indefinite);
169
170 let l = Length::from(2);
171 assert_eq!(l + Length::from(2), Length::from(4));
172
173 let l = Length::Indefinite;
174 assert_eq!(l + Length::from(2), Length::Indefinite);
175
176 let mut l = Length::from(2);
177 l += 2;
178 assert_eq!(l.definite(), Ok(4));
179
180 let mut l = Length::Indefinite;
181 l += 2;
182 assert_eq!(l, Length::Indefinite);
183 }
184}