/rust/registry/src/index.crates.io-6f17d22bba15001f/asn1-rs-0.7.1/src/traits.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use crate::debug::{trace, trace_generic}; |
2 | | use crate::error::*; |
3 | | use crate::{parse_der_any, Any, Class, Explicit, Implicit, Tag, TaggedParser}; |
4 | | use core::convert::{TryFrom, TryInto}; |
5 | | use core::fmt::{Debug, Display}; |
6 | | #[cfg(feature = "std")] |
7 | | use std::io::Write; |
8 | | |
9 | | /// Phantom type representing a BER parser |
10 | | #[doc(hidden)] |
11 | | #[derive(Debug)] |
12 | | pub enum BerParser {} |
13 | | |
14 | | /// Phantom type representing a DER parser |
15 | | #[doc(hidden)] |
16 | | #[derive(Debug)] |
17 | | pub enum DerParser {} |
18 | | |
19 | | #[doc(hidden)] |
20 | | pub trait ASN1Parser {} |
21 | | |
22 | | impl ASN1Parser for BerParser {} |
23 | | impl ASN1Parser for DerParser {} |
24 | | |
25 | | pub trait Tagged { |
26 | | const TAG: Tag; |
27 | | } |
28 | | |
29 | | impl<T> Tagged for &'_ T |
30 | | where |
31 | | T: Tagged, |
32 | | { |
33 | | const TAG: Tag = T::TAG; |
34 | | } |
35 | | |
36 | | pub trait DynTagged { |
37 | | fn tag(&self) -> Tag; |
38 | | } |
39 | | |
40 | | impl<T> DynTagged for T |
41 | | where |
42 | | T: Tagged, |
43 | | { |
44 | 0 | fn tag(&self) -> Tag { |
45 | 0 | T::TAG |
46 | 0 | } |
47 | | } |
48 | | |
49 | | /// Base trait for BER object parsers |
50 | | /// |
51 | | /// Library authors should usually not directly implement this trait, but should prefer implementing the |
52 | | /// [`TryFrom<Any>`] trait, |
53 | | /// which offers greater flexibility and provides an equivalent `FromBer` implementation for free. |
54 | | /// |
55 | | /// # Examples |
56 | | /// |
57 | | /// ``` |
58 | | /// use asn1_rs::{Any, Result, Tag}; |
59 | | /// use std::convert::TryFrom; |
60 | | /// |
61 | | /// // The type to be decoded |
62 | | /// #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
63 | | /// pub struct MyType(pub u32); |
64 | | /// |
65 | | /// impl<'a> TryFrom<Any<'a>> for MyType { |
66 | | /// type Error = asn1_rs::Error; |
67 | | /// |
68 | | /// fn try_from(any: Any<'a>) -> Result<MyType> { |
69 | | /// any.tag().assert_eq(Tag::Integer)?; |
70 | | /// // for this fictive example, the type contains the number of characters |
71 | | /// let n = any.data.len() as u32; |
72 | | /// Ok(MyType(n)) |
73 | | /// } |
74 | | /// } |
75 | | /// |
76 | | /// // The above code provides a `FromBer` implementation for free. |
77 | | /// |
78 | | /// // Example of parsing code: |
79 | | /// use asn1_rs::FromBer; |
80 | | /// |
81 | | /// let input = &[2, 1, 2]; |
82 | | /// // Objects can be parsed using `from_ber`, which returns the remaining bytes |
83 | | /// // and the parsed object: |
84 | | /// let (rem, my_type) = MyType::from_ber(input).expect("parsing failed"); |
85 | | /// ``` |
86 | | pub trait FromBer<'a, E = Error>: Sized { |
87 | | /// Attempt to parse input bytes into a BER object |
88 | | fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, Self, E>; |
89 | | } |
90 | | |
91 | | impl<'a, T, E> FromBer<'a, E> for T |
92 | | where |
93 | | T: TryFrom<Any<'a>, Error = E>, |
94 | | E: From<Error>, |
95 | | { |
96 | 2.39M | fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, T, E> { |
97 | 2.39M | let (i, any) = Any::from_ber(bytes).map_err(nom::Err::convert)?; |
98 | 2.23M | let result = any.try_into().map_err(nom::Err::Error)?; |
99 | 2.22M | Ok((i, result)) |
100 | 2.39M | } <asn1_rs::asn1_types::set::Set as asn1_rs::traits::FromBer>::from_ber Line | Count | Source | 96 | 7.74k | fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, T, E> { | 97 | 7.74k | let (i, any) = Any::from_ber(bytes).map_err(nom::Err::convert)?; | 98 | 6.69k | let result = any.try_into().map_err(nom::Err::Error)?; | 99 | 6.22k | Ok((i, result)) | 100 | 7.74k | } |
<&[u8] as asn1_rs::traits::FromBer>::from_ber Line | Count | Source | 96 | 167k | fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, T, E> { | 97 | 167k | let (i, any) = Any::from_ber(bytes).map_err(nom::Err::convert)?; | 98 | 126k | let result = any.try_into().map_err(nom::Err::Error)?; | 99 | 121k | Ok((i, result)) | 100 | 167k | } |
<bool as asn1_rs::traits::FromBer>::from_ber Line | Count | Source | 96 | 16.2k | fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, T, E> { | 97 | 16.2k | let (i, any) = Any::from_ber(bytes).map_err(nom::Err::convert)?; | 98 | 14.1k | let result = any.try_into().map_err(nom::Err::Error)?; | 99 | 13.7k | Ok((i, result)) | 100 | 16.2k | } |
<u8 as asn1_rs::traits::FromBer>::from_ber Line | Count | Source | 96 | 4.50k | fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, T, E> { | 97 | 4.50k | let (i, any) = Any::from_ber(bytes).map_err(nom::Err::convert)?; | 98 | 4.26k | let result = any.try_into().map_err(nom::Err::Error)?; | 99 | 4.16k | Ok((i, result)) | 100 | 4.50k | } |
<u32 as asn1_rs::traits::FromBer>::from_ber Line | Count | Source | 96 | 1.01M | fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, T, E> { | 97 | 1.01M | let (i, any) = Any::from_ber(bytes).map_err(nom::Err::convert)?; | 98 | 1.00M | let result = any.try_into().map_err(nom::Err::Error)?; | 99 | 1.00M | Ok((i, result)) | 100 | 1.01M | } |
<() as asn1_rs::traits::FromBer>::from_ber Line | Count | Source | 96 | 1.48k | fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, T, E> { | 97 | 1.48k | let (i, any) = Any::from_ber(bytes).map_err(nom::Err::convert)?; | 98 | 538 | let result = any.try_into().map_err(nom::Err::Error)?; | 99 | 456 | Ok((i, result)) | 100 | 1.48k | } |
<asn1_rs::asn1_types::tagged::TaggedValue<bool, asn1_rs::error::Error, asn1_rs::asn1_types::tagged::Implicit, 2, 4> as asn1_rs::traits::FromBer>::from_ber Line | Count | Source | 96 | 428 | fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, T, E> { | 97 | 428 | let (i, any) = Any::from_ber(bytes).map_err(nom::Err::convert)?; | 98 | 206 | let result = any.try_into().map_err(nom::Err::Error)?; | 99 | 200 | Ok((i, result)) | 100 | 428 | } |
<asn1_rs::asn1_types::tagged::TaggedValue<u32, asn1_rs::error::Error, asn1_rs::asn1_types::tagged::Implicit, 1, 16> as asn1_rs::traits::FromBer>::from_ber Line | Count | Source | 96 | 2.30k | fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, T, E> { | 97 | 2.30k | let (i, any) = Any::from_ber(bytes).map_err(nom::Err::convert)?; | 98 | 1.61k | let result = any.try_into().map_err(nom::Err::Error)?; | 99 | 1.59k | Ok((i, result)) | 100 | 2.30k | } |
<asn1_rs::asn1_types::enumerated::Enumerated as asn1_rs::traits::FromBer>::from_ber Line | Count | Source | 96 | 39.0k | fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, T, E> { | 97 | 39.0k | let (i, any) = Any::from_ber(bytes).map_err(nom::Err::convert)?; | 98 | 36.7k | let result = any.try_into().map_err(nom::Err::Error)?; | 99 | 36.5k | Ok((i, result)) | 100 | 39.0k | } |
Unexecuted instantiation: <asn1_rs::asn1_types::oid::Oid as asn1_rs::traits::FromBer>::from_ber <asn1_rs::asn1_types::sequence::Sequence as asn1_rs::traits::FromBer>::from_ber Line | Count | Source | 96 | 1.14M | fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, T, E> { | 97 | 1.14M | let (i, any) = Any::from_ber(bytes).map_err(nom::Err::convert)?; | 98 | 1.03M | let result = any.try_into().map_err(nom::Err::Error)?; | 99 | 1.03M | Ok((i, result)) | 100 | 1.14M | } |
|
101 | | } |
102 | | |
103 | | /// Base trait for DER object parsers |
104 | | /// |
105 | | /// Library authors should usually not directly implement this trait, but should prefer implementing the |
106 | | /// [`TryFrom<Any>`] + [`CheckDerConstraints`] traits, |
107 | | /// which offers greater flexibility and provides an equivalent `FromDer` implementation for free |
108 | | /// (in fact, it provides both [`FromBer`] and `FromDer`). |
109 | | /// |
110 | | /// Note: if you already implemented [`TryFrom<Any>`] and [`CheckDerConstraints`], |
111 | | /// you can get a free [`FromDer`] implementation by implementing the |
112 | | /// [`DerAutoDerive`] trait. This is not automatic, so it is also possible to manually |
113 | | /// implement [`FromDer`] if preferred. |
114 | | /// |
115 | | /// # Examples |
116 | | /// |
117 | | /// ``` |
118 | | /// use asn1_rs::{Any, CheckDerConstraints, DerAutoDerive, Result, Tag}; |
119 | | /// use std::convert::TryFrom; |
120 | | /// |
121 | | /// // The type to be decoded |
122 | | /// #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
123 | | /// pub struct MyType(pub u32); |
124 | | /// |
125 | | /// impl<'a> TryFrom<Any<'a>> for MyType { |
126 | | /// type Error = asn1_rs::Error; |
127 | | /// |
128 | | /// fn try_from(any: Any<'a>) -> Result<MyType> { |
129 | | /// any.tag().assert_eq(Tag::Integer)?; |
130 | | /// // for this fictive example, the type contains the number of characters |
131 | | /// let n = any.data.len() as u32; |
132 | | /// Ok(MyType(n)) |
133 | | /// } |
134 | | /// } |
135 | | /// |
136 | | /// impl CheckDerConstraints for MyType { |
137 | | /// fn check_constraints(any: &Any) -> Result<()> { |
138 | | /// any.header.assert_primitive()?; |
139 | | /// Ok(()) |
140 | | /// } |
141 | | /// } |
142 | | /// |
143 | | /// impl DerAutoDerive for MyType {} |
144 | | /// |
145 | | /// // The above code provides a `FromDer` implementation for free. |
146 | | /// |
147 | | /// // Example of parsing code: |
148 | | /// use asn1_rs::FromDer; |
149 | | /// |
150 | | /// let input = &[2, 1, 2]; |
151 | | /// // Objects can be parsed using `from_der`, which returns the remaining bytes |
152 | | /// // and the parsed object: |
153 | | /// let (rem, my_type) = MyType::from_der(input).expect("parsing failed"); |
154 | | /// ``` |
155 | | pub trait FromDer<'a, E = Error>: Sized { |
156 | | /// Attempt to parse input bytes into a DER object (enforcing constraints) |
157 | | fn from_der(bytes: &'a [u8]) -> ParseResult<'a, Self, E>; |
158 | | } |
159 | | |
160 | | /// Trait to automatically derive `FromDer` |
161 | | /// |
162 | | /// This trait is only a marker to control if a DER parser should be automatically derived. It is |
163 | | /// empty. |
164 | | /// |
165 | | /// This trait is used in combination with others: |
166 | | /// after implementing [`TryFrom<Any>`] and [`CheckDerConstraints`] for a type, |
167 | | /// a free [`FromDer`] implementation is provided by implementing the |
168 | | /// [`DerAutoDerive`] trait. This is the most common case. |
169 | | /// |
170 | | /// However, this is not automatic so it is also possible to manually |
171 | | /// implement [`FromDer`] if preferred. |
172 | | /// Manual implementation is generally only needed for generic containers (for ex. `Vec<T>`), |
173 | | /// because the default implementation adds a constraint on `T` to implement also `TryFrom<Any>` |
174 | | /// and `CheckDerConstraints`. This is problematic when `T` only provides `FromDer`, and can be |
175 | | /// solved by providing a manual implementation of [`FromDer`]. |
176 | | pub trait DerAutoDerive {} |
177 | | |
178 | | impl<'a, T, E> FromDer<'a, E> for T |
179 | | where |
180 | | T: TryFrom<Any<'a>, Error = E>, |
181 | | T: CheckDerConstraints, |
182 | | T: DerAutoDerive, |
183 | | E: From<Error> + Display + Debug, |
184 | | { |
185 | 0 | fn from_der(bytes: &'a [u8]) -> ParseResult<'a, T, E> { |
186 | 0 | trace_generic( |
187 | 0 | core::any::type_name::<T>(), |
188 | 0 | "T::from_der", |
189 | 0 | |bytes| { |
190 | 0 | let (i, any) = trace(core::any::type_name::<T>(), parse_der_any, bytes) |
191 | 0 | .map_err(nom::Err::convert)?; |
192 | 0 | <T as CheckDerConstraints>::check_constraints(&any) |
193 | 0 | .map_err(|e| nom::Err::Error(e.into()))?; |
194 | 0 | let result = any.try_into().map_err(nom::Err::Error)?; |
195 | 0 | Ok((i, result)) |
196 | 0 | }, |
197 | 0 | bytes, |
198 | 0 | ) |
199 | 0 | } |
200 | | } |
201 | | |
202 | | /// Verification of DER constraints |
203 | | pub trait CheckDerConstraints { |
204 | | fn check_constraints(any: &Any) -> Result<()>; |
205 | | } |
206 | | |
207 | | /// Common trait for all objects that can be encoded using the DER representation |
208 | | /// |
209 | | /// # Examples |
210 | | /// |
211 | | /// Objects from this crate can be encoded as DER: |
212 | | /// |
213 | | /// ``` |
214 | | /// use asn1_rs::{Integer, ToDer}; |
215 | | /// |
216 | | /// let int = Integer::from(4u32); |
217 | | /// let mut writer = Vec::new(); |
218 | | /// let sz = int.write_der(&mut writer).expect("serialization failed"); |
219 | | /// |
220 | | /// assert_eq!(&writer, &[0x02, 0x01, 0x04]); |
221 | | /// # assert_eq!(sz, 3); |
222 | | /// ``` |
223 | | /// |
224 | | /// Many of the primitive types can also directly be encoded as DER: |
225 | | /// |
226 | | /// ``` |
227 | | /// use asn1_rs::ToDer; |
228 | | /// |
229 | | /// let mut writer = Vec::new(); |
230 | | /// let sz = 4.write_der(&mut writer).expect("serialization failed"); |
231 | | /// |
232 | | /// assert_eq!(&writer, &[0x02, 0x01, 0x04]); |
233 | | /// # assert_eq!(sz, 3); |
234 | | /// ``` |
235 | | #[cfg(feature = "std")] |
236 | | pub trait ToDer |
237 | | where |
238 | | Self: DynTagged, |
239 | | { |
240 | | /// Get the length of the object (including the header), when encoded |
241 | | /// |
242 | | // Since we are using DER, length cannot be Indefinite, so we can use `usize`. |
243 | | // XXX can this function fail? |
244 | | fn to_der_len(&self) -> Result<usize>; |
245 | | |
246 | | /// Write the DER encoded representation to a newly allocated `Vec<u8>`. |
247 | 0 | fn to_der_vec(&self) -> SerializeResult<Vec<u8>> { |
248 | 0 | let mut v = Vec::new(); |
249 | 0 | let _ = self.write_der(&mut v)?; |
250 | 0 | Ok(v) |
251 | 0 | } |
252 | | |
253 | | /// Similar to using `to_vec`, but uses provided values without changes. |
254 | | /// This can generate an invalid encoding for a DER object. |
255 | 0 | fn to_der_vec_raw(&self) -> SerializeResult<Vec<u8>> { |
256 | 0 | let mut v = Vec::new(); |
257 | 0 | let _ = self.write_der_raw(&mut v)?; |
258 | 0 | Ok(v) |
259 | 0 | } |
260 | | |
261 | | /// Attempt to write the DER encoded representation (header and content) into this writer. |
262 | | /// |
263 | | /// # Examples |
264 | | /// |
265 | | /// ``` |
266 | | /// use asn1_rs::{Integer, ToDer}; |
267 | | /// |
268 | | /// let int = Integer::from(4u32); |
269 | | /// let mut writer = Vec::new(); |
270 | | /// let sz = int.write_der(&mut writer).expect("serialization failed"); |
271 | | /// |
272 | | /// assert_eq!(&writer, &[0x02, 0x01, 0x04]); |
273 | | /// # assert_eq!(sz, 3); |
274 | | /// ``` |
275 | 0 | fn write_der(&self, writer: &mut dyn Write) -> SerializeResult<usize> { |
276 | 0 | let sz = self.write_der_header(writer)?; |
277 | 0 | let sz = sz + self.write_der_content(writer)?; |
278 | 0 | Ok(sz) |
279 | 0 | } |
280 | | |
281 | | /// Attempt to write the DER header to this writer. |
282 | | fn write_der_header(&self, writer: &mut dyn Write) -> SerializeResult<usize>; |
283 | | |
284 | | /// Attempt to write the DER content (all except header) to this writer. |
285 | | fn write_der_content(&self, writer: &mut dyn Write) -> SerializeResult<usize>; |
286 | | |
287 | | /// Similar to using `to_der`, but uses provided values without changes. |
288 | | /// This can generate an invalid encoding for a DER object. |
289 | 0 | fn write_der_raw(&self, writer: &mut dyn Write) -> SerializeResult<usize> { |
290 | 0 | self.write_der(writer) |
291 | 0 | } |
292 | | } |
293 | | |
294 | | #[cfg(feature = "std")] |
295 | | impl<'a, T> ToDer for &'a T |
296 | | where |
297 | | T: ToDer, |
298 | | &'a T: DynTagged, |
299 | | { |
300 | 0 | fn to_der_len(&self) -> Result<usize> { |
301 | 0 | (*self).to_der_len() |
302 | 0 | } |
303 | | |
304 | 0 | fn write_der_header(&self, writer: &mut dyn Write) -> SerializeResult<usize> { |
305 | 0 | (*self).write_der_header(writer) |
306 | 0 | } |
307 | | |
308 | 0 | fn write_der_content(&self, writer: &mut dyn Write) -> SerializeResult<usize> { |
309 | 0 | (*self).write_der_content(writer) |
310 | 0 | } |
311 | | } |
312 | | |
313 | | /// Helper trait for creating tagged EXPLICIT values |
314 | | /// |
315 | | /// # Examples |
316 | | /// |
317 | | /// ``` |
318 | | /// use asn1_rs::{AsTaggedExplicit, Class, Error, TaggedParser}; |
319 | | /// |
320 | | /// // create a `[1] EXPLICIT INTEGER` value |
321 | | /// let tagged: TaggedParser<_, _, Error> = 4u32.explicit(Class::ContextSpecific, 1); |
322 | | /// ``` |
323 | | pub trait AsTaggedExplicit<'a, E = Error>: Sized { |
324 | 0 | fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E> { |
325 | 0 | TaggedParser::new_explicit(class, tag, self) |
326 | 0 | } |
327 | | } |
328 | | |
329 | | impl<'a, T, E> AsTaggedExplicit<'a, E> for T where T: Sized + 'a {} |
330 | | |
331 | | /// Helper trait for creating tagged IMPLICIT values |
332 | | /// |
333 | | /// # Examples |
334 | | /// |
335 | | /// ``` |
336 | | /// use asn1_rs::{AsTaggedImplicit, Class, Error, TaggedParser}; |
337 | | /// |
338 | | /// // create a `[1] IMPLICIT INTEGER` value, not constructed |
339 | | /// let tagged: TaggedParser<_, _, Error> = 4u32.implicit(Class::ContextSpecific, false, 1); |
340 | | /// ``` |
341 | | pub trait AsTaggedImplicit<'a, E = Error>: Sized { |
342 | 0 | fn implicit( |
343 | 0 | self, |
344 | 0 | class: Class, |
345 | 0 | constructed: bool, |
346 | 0 | tag: u32, |
347 | 0 | ) -> TaggedParser<'a, Implicit, Self, E> { |
348 | 0 | TaggedParser::new_implicit(class, constructed, tag, self) |
349 | 0 | } |
350 | | } |
351 | | |
352 | | impl<'a, T, E> AsTaggedImplicit<'a, E> for T where T: Sized + 'a {} |
353 | | |
354 | | pub use crate::tostatic::*; |