/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 | | } |