Coverage Report

Created: 2025-07-23 07:29

/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::*;