asn1_rs/
length.rs

1use core::iter::Sum;
2use core::ops;
3
4use crate::{DynTagged, Error, InnerError, Result, Tag};
5
6/// BER Object Length
7#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
8pub enum Length {
9    /// Definite form (X.690 8.1.3.3)
10    Definite(usize),
11    /// Indefinite form (X.690 8.1.3.6)
12    Indefinite,
13}
14
15impl Length {
16    /// Return true if length is definite and equal to 0
17    #[inline]
18    pub fn is_null(&self) -> bool {
19        *self == Length::Definite(0)
20    }
21
22    /// Get length of primitive object
23    #[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    /// Get length of primitive object
32    #[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    /// Return true if length is definite
41    #[inline]
42    pub const fn is_definite(&self) -> bool {
43        matches!(self, Length::Definite(_))
44    }
45
46    /// Return error if length is not definite
47    #[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    /// Return error if length is not definite
56    #[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    /// Generic and coverage tests
153    #[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}