-
Notifications
You must be signed in to change notification settings - Fork 175
Expand file tree
/
Copy pathdecode.rs
More file actions
160 lines (135 loc) · 5.35 KB
/
decode.rs
File metadata and controls
160 lines (135 loc) · 5.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//! Trait definition for [`Decode`].
use crate::{Error, FixedTag, Header, Reader, SliceReader, reader::read_value};
use core::marker::PhantomData;
#[cfg(feature = "pem")]
use crate::{PemReader, pem::PemLabel};
#[cfg(doc)]
use crate::{ErrorKind, Length, Tag};
#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "ber")]
use crate::EncodingRules;
/// Decoding trait.
///
/// This trait provides the core abstraction upon which all decoding operations
/// are based.
#[diagnostic::on_unimplemented(
note = "Consider adding impls of `DecodeValue` and `FixedTag` to `{Self}`"
)]
pub trait Decode<'a>: Sized + 'a {
/// Type returned in the event of a decoding error.
type Error: From<Error> + 'static;
/// Attempt to decode this message using the provided decoder.
fn decode<R: Reader<'a>>(decoder: &mut R) -> Result<Self, Self::Error>;
/// Parse `Self` from the provided BER-encoded byte slice.
///
/// Note that most usages should probably use [`Decode::from_der`]. This method allows some
/// BER productions which are not allowed under DER.
#[cfg(feature = "ber")]
fn from_ber(bytes: &'a [u8]) -> Result<Self, Self::Error> {
let mut reader = SliceReader::new_with_encoding_rules(bytes, EncodingRules::Ber)?;
let result = Self::decode(&mut reader)?;
reader.finish()?;
Ok(result)
}
/// Parse `Self` from the provided DER-encoded byte slice.
///
/// Returns [`ErrorKind::TrailingData`] if message is incomplete.
fn from_der(bytes: &'a [u8]) -> Result<Self, Self::Error> {
let mut reader = SliceReader::new(bytes)?;
let result = Self::decode(&mut reader)?;
reader.finish()?;
Ok(result)
}
/// Parse `Self` from the provided DER-encoded byte slice.
///
/// Returns remaining byte slice, without checking for incomplete message.
fn from_der_partial(bytes: &'a [u8]) -> Result<(Self, &'a [u8]), Self::Error> {
let mut reader = SliceReader::new(bytes)?;
let result = Self::decode(&mut reader)?;
let remaining = reader.remaining()?;
Ok((result, remaining))
}
}
impl<'a, T> Decode<'a> for T
where
T: DecodeValue<'a> + FixedTag + 'a,
{
type Error = <T as DecodeValue<'a>>::Error;
fn decode<R: Reader<'a>>(reader: &mut R) -> Result<T, <T as DecodeValue<'a>>::Error> {
let header = Header::decode(reader)?;
header.tag().assert_eq(T::TAG)?;
read_value(reader, header, T::decode_value_nested)
}
}
/// Dummy implementation for [`PhantomData`] which allows deriving
/// implementations on structs with phantom fields.
impl<'a, T> Decode<'a> for PhantomData<T>
where
T: ?Sized + 'a,
{
type Error = Error;
fn decode<R: Reader<'a>>(_reader: &mut R) -> Result<PhantomData<T>, Error> {
Ok(PhantomData)
}
}
/// Marker trait for data structures that can be decoded from DER without
/// borrowing any data from the decoder.
///
/// This is primarily useful for trait bounds on functions which require that
/// no data is borrowed from the decoder, for example a PEM decoder which needs
/// to first decode data from Base64.
///
/// This trait is inspired by the [`DeserializeOwned` trait from `serde`](https://docs.rs/serde/latest/serde/de/trait.DeserializeOwned.html).
#[diagnostic::on_unimplemented(
note = "`DecodeOwned` is auto-impl'd for all lifetime-free types which impl `Decode`"
)]
pub trait DecodeOwned: for<'a> Decode<'a> {}
impl<T> DecodeOwned for T where T: for<'a> Decode<'a> {}
/// PEM decoding trait.
///
/// This trait is automatically impl'd for any type which impls both
/// [`DecodeOwned`] and [`PemLabel`].
#[cfg(feature = "pem")]
#[diagnostic::on_unimplemented(
note = "`DecodePem` is auto-impl'd for all lifetime-free types which impl both `Decode` and `PemLabel`"
)]
pub trait DecodePem: DecodeOwned + PemLabel {
/// Try to decode this type from PEM.
fn from_pem(pem: impl AsRef<[u8]>) -> Result<Self, <Self as Decode<'static>>::Error>;
}
#[cfg(feature = "pem")]
impl<T: DecodeOwned<Error = Error> + PemLabel> DecodePem for T {
fn from_pem(pem: impl AsRef<[u8]>) -> Result<T, Error> {
let mut reader = PemReader::new(pem.as_ref())?;
Self::validate_pem_label(reader.type_label()).map_err(Error::from)?;
T::decode(&mut reader)
}
}
/// Decode the value part of a Tag-Length-Value encoded field, sans the [`Tag`]
/// and [`Length`].
pub trait DecodeValue<'a>: Sized {
/// Type returned in the event of a decoding error.
type Error: From<Error> + 'static;
/// Attempt to decode this message using the provided [`Reader`].
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self, Self::Error>;
/// Attempt to decode this message using the nested [`Reader`], using [`Reader::read_nested`] wrapper.
///
/// For primitive types, this function can be overridden to [`DecodeValue::decode_value`] directly.
fn decode_value_nested<R: Reader<'a>>(
reader: &mut R,
header: Header,
) -> Result<Self, Self::Error> {
reader.read_nested(header.length(), |r| Self::decode_value(r, header))
}
}
#[cfg(feature = "alloc")]
impl<'a, T> DecodeValue<'a> for Box<T>
where
T: DecodeValue<'a>,
{
type Error = T::Error;
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self, Self::Error> {
Ok(Box::new(T::decode_value(reader, header)?))
}
}