Coverage Report

Created: 2025-11-04 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/der-0.7.10/src/decode.rs
Line
Count
Source
1
//! Trait definition for [`Decode`].
2
3
use crate::{FixedTag, Header, Reader, Result, SliceReader};
4
use core::marker::PhantomData;
5
6
#[cfg(feature = "pem")]
7
use crate::{pem::PemLabel, PemReader};
8
9
#[cfg(doc)]
10
use crate::{Length, Tag};
11
12
#[cfg(feature = "alloc")]
13
use alloc::boxed::Box;
14
15
/// Decoding trait.
16
///
17
/// This trait provides the core abstraction upon which all decoding operations
18
/// are based.
19
pub trait Decode<'a>: Sized {
20
    /// Attempt to decode this message using the provided decoder.
21
    fn decode<R: Reader<'a>>(decoder: &mut R) -> Result<Self>;
22
23
    /// Parse `Self` from the provided DER-encoded byte slice.
24
0
    fn from_der(bytes: &'a [u8]) -> Result<Self> {
25
0
        let mut reader = SliceReader::new(bytes)?;
26
0
        let result = Self::decode(&mut reader)?;
27
0
        reader.finish(result)
28
0
    }
Unexecuted instantiation: <der::document::Document as der::decode::Decode>::from_der
Unexecuted instantiation: <der::asn1::any::AnyRef as der::decode::Decode>::from_der
29
}
30
31
impl<'a, T> Decode<'a> for T
32
where
33
    T: DecodeValue<'a> + FixedTag,
34
{
35
0
    fn decode<R: Reader<'a>>(reader: &mut R) -> Result<T> {
36
0
        let header = Header::decode(reader)?;
37
0
        header.tag.assert_eq(T::TAG)?;
38
0
        T::decode_value(reader, header)
39
0
    }
40
}
41
42
/// Dummy implementation for [`PhantomData`] which allows deriving
43
/// implementations on structs with phantom fields.
44
impl<'a, T> Decode<'a> for PhantomData<T>
45
where
46
    T: ?Sized,
47
{
48
0
    fn decode<R: Reader<'a>>(_reader: &mut R) -> Result<PhantomData<T>> {
49
0
        Ok(PhantomData)
50
0
    }
51
}
52
53
/// Marker trait for data structures that can be decoded from DER without
54
/// borrowing any data from the decoder.
55
///
56
/// This is primarily useful for trait bounds on functions which require that
57
/// no data is borrowed from the decoder, for example a PEM decoder which needs
58
/// to first decode data from Base64.
59
///
60
/// This trait is inspired by the [`DeserializeOwned` trait from `serde`](https://docs.rs/serde/latest/serde/de/trait.DeserializeOwned.html).
61
pub trait DecodeOwned: for<'a> Decode<'a> {}
62
63
impl<T> DecodeOwned for T where T: for<'a> Decode<'a> {}
64
65
/// PEM decoding trait.
66
///
67
/// This trait is automatically impl'd for any type which impls both
68
/// [`DecodeOwned`] and [`PemLabel`].
69
#[cfg(feature = "pem")]
70
pub trait DecodePem: DecodeOwned + PemLabel {
71
    /// Try to decode this type from PEM.
72
    fn from_pem(pem: impl AsRef<[u8]>) -> Result<Self>;
73
}
74
75
#[cfg(feature = "pem")]
76
impl<T: DecodeOwned + PemLabel> DecodePem for T {
77
    fn from_pem(pem: impl AsRef<[u8]>) -> Result<Self> {
78
        let mut reader = PemReader::new(pem.as_ref())?;
79
        Self::validate_pem_label(reader.type_label())?;
80
        T::decode(&mut reader)
81
    }
82
}
83
84
/// Decode the value part of a Tag-Length-Value encoded field, sans the [`Tag`]
85
/// and [`Length`].
86
pub trait DecodeValue<'a>: Sized {
87
    /// Attempt to decode this message using the provided [`Reader`].
88
    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self>;
89
}
90
91
#[cfg(feature = "alloc")]
92
impl<'a, T> DecodeValue<'a> for Box<T>
93
where
94
    T: DecodeValue<'a>,
95
{
96
0
    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
97
0
        Ok(Box::new(T::decode_value(reader, header)?))
98
0
    }
99
}