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. decode<R: Reader<'a>>(decoder: &mut R) -> Result<Self>21 fn decode<R: Reader<'a>>(decoder: &mut R) -> Result<Self>; 22 23 /// Parse `Self` from the provided DER-encoded byte slice. from_der(bytes: &'a [u8]) -> Result<Self>24 fn from_der(bytes: &'a [u8]) -> Result<Self> { 25 let mut reader = SliceReader::new(bytes)?; 26 let result = Self::decode(&mut reader)?; 27 reader.finish(result) 28 } 29 } 30 31 impl<'a, T> Decode<'a> for T 32 where 33 T: DecodeValue<'a> + FixedTag, 34 { decode<R: Reader<'a>>(reader: &mut R) -> Result<T>35 fn decode<R: Reader<'a>>(reader: &mut R) -> Result<T> { 36 let header = Header::decode(reader)?; 37 header.tag.assert_eq(T::TAG)?; 38 T::decode_value(reader, header) 39 } 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 { decode<R: Reader<'a>>(_reader: &mut R) -> Result<PhantomData<T>>48 fn decode<R: Reader<'a>>(_reader: &mut R) -> Result<PhantomData<T>> { 49 Ok(PhantomData) 50 } 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. from_pem(pem: impl AsRef<[u8]>) -> Result<Self>72 fn from_pem(pem: impl AsRef<[u8]>) -> Result<Self>; 73 } 74 75 #[cfg(feature = "pem")] 76 impl<T: DecodeOwned + PemLabel> DecodePem for T { from_pem(pem: impl AsRef<[u8]>) -> Result<Self>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`]. decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self>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 { decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self>96 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { 97 Ok(Box::new(T::decode_value(reader, header)?)) 98 } 99 } 100