Coverage Report

Created: 2025-07-23 07:29

/rust/registry/src/index.crates.io-6f17d22bba15001f/asn1-rs-0.5.2/src/length.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{DynTagged, Error, Result, Tag};
2
#[cfg(feature = "std")]
3
use crate::{SerializeResult, ToDer};
4
use core::ops;
5
6
/// BER Object Length
7
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
8
pub 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
15
impl Length {
16
    /// Return true if length is definite and equal to 0
17
    #[inline]
18
0
    pub fn is_null(&self) -> bool {
19
0
        *self == Length::Definite(0)
20
0
    }
21
22
    /// Get length of primitive object
23
    #[inline]
24
93.7k
    pub fn definite(&self) -> Result<usize> {
25
93.7k
        match self {
26
93.7k
            Length::Definite(sz) => Ok(*sz),
27
0
            Length::Indefinite => Err(Error::IndefiniteLengthUnexpected),
28
        }
29
93.7k
    }
30
31
    /// Return true if length is definite
32
    #[inline]
33
0
    pub const fn is_definite(&self) -> bool {
34
0
        matches!(self, Length::Definite(_))
35
0
    }
36
37
    /// Return error if length is not definite
38
    #[inline]
39
267k
    pub const fn assert_definite(&self) -> Result<()> {
40
267k
        match self {
41
267k
            Length::Definite(_) => Ok(()),
42
0
            Length::Indefinite => Err(Error::IndefiniteLengthUnexpected),
43
        }
44
267k
    }
45
}
46
47
impl From<usize> for Length {
48
0
    fn from(l: usize) -> Self {
49
0
        Length::Definite(l)
50
0
    }
51
}
52
53
impl ops::Add<Length> for Length {
54
    type Output = Self;
55
56
0
    fn add(self, rhs: Length) -> Self::Output {
57
0
        match self {
58
0
            Length::Indefinite => self,
59
0
            Length::Definite(lhs) => match rhs {
60
0
                Length::Indefinite => rhs,
61
0
                Length::Definite(rhs) => Length::Definite(lhs + rhs),
62
            },
63
        }
64
0
    }
65
}
66
67
impl ops::Add<usize> for Length {
68
    type Output = Self;
69
70
0
    fn add(self, rhs: usize) -> Self::Output {
71
0
        match self {
72
0
            Length::Definite(lhs) => Length::Definite(lhs + rhs),
73
0
            Length::Indefinite => self,
74
        }
75
0
    }
76
}
77
78
impl ops::AddAssign<usize> for Length {
79
0
    fn add_assign(&mut self, rhs: usize) {
80
0
        match self {
81
0
            Length::Definite(ref mut lhs) => *lhs += rhs,
82
0
            Length::Indefinite => (),
83
        }
84
0
    }
85
}
86
87
impl DynTagged for Length {
88
0
    fn tag(&self) -> Tag {
89
0
        Tag(0)
90
0
    }
91
}
92
93
#[cfg(feature = "std")]
94
impl ToDer for Length {
95
0
    fn to_der_len(&self) -> Result<usize> {
96
0
        match self {
97
0
            Length::Indefinite => Ok(1),
98
0
            Length::Definite(l) => match l {
99
0
                0..=0x7f => Ok(1),
100
0
                0x80..=0xff => Ok(2),
101
0
                0x100..=0xffff => Ok(3),
102
0
                0x1_0000..=0xffff_ffff => Ok(4),
103
0
                _ => Err(Error::InvalidLength),
104
            },
105
        }
106
0
    }
107
108
0
    fn write_der_header(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
109
0
        match *self {
110
            Length::Indefinite => {
111
0
                let sz = writer.write(&[0b1000_0000])?;
112
0
                Ok(sz)
113
            }
114
0
            Length::Definite(l) => {
115
0
                if l <= 127 {
116
                    // Short form
117
0
                    let sz = writer.write(&[l as u8])?;
118
0
                    Ok(sz)
119
                } else {
120
                    // Long form
121
0
                    let b = l.to_be_bytes();
122
0
                    // skip leading zeroes
123
0
                    // we do not have to test for length, l cannot be 0
124
0
                    let mut idx = 0;
125
0
                    while b[idx] == 0 {
126
0
                        idx += 1;
127
0
                    }
128
0
                    let b = &b[idx..];
129
0
                    // first byte: 0x80 + length of length
130
0
                    let b0 = 0x80 | (b.len() as u8);
131
0
                    let sz = writer.write(&[b0])?;
132
0
                    let sz = sz + writer.write(b)?;
133
0
                    Ok(sz)
134
                }
135
            }
136
        }
137
0
    }
138
139
0
    fn write_der_content(&self, _writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
140
0
        Ok(0)
141
0
    }
142
}
143
144
#[cfg(test)]
145
mod tests {
146
    use crate::*;
147
148
    /// Generic and coverage tests
149
    #[test]
150
    fn methods_length() {
151
        let l = Length::from(2);
152
        assert_eq!(l.definite(), Ok(2));
153
        assert!(l.assert_definite().is_ok());
154
155
        let l = Length::Indefinite;
156
        assert!(l.definite().is_err());
157
        assert!(l.assert_definite().is_err());
158
159
        let l = Length::from(2);
160
        assert_eq!(l + 2, Length::from(4));
161
        assert_eq!(l + Length::Indefinite, Length::Indefinite);
162
163
        let l = Length::Indefinite;
164
        assert_eq!(l + 2, Length::Indefinite);
165
166
        let l = Length::from(2);
167
        assert_eq!(l + Length::from(2), Length::from(4));
168
169
        let l = Length::Indefinite;
170
        assert_eq!(l + Length::from(2), Length::Indefinite);
171
172
        let mut l = Length::from(2);
173
        l += 2;
174
        assert_eq!(l.definite(), Ok(4));
175
176
        let mut l = Length::Indefinite;
177
        l += 2;
178
        assert_eq!(l, Length::Indefinite);
179
    }
180
}