1 //! Trait definition for [`Encode`]. 2 3 use crate::{Header, Length, Result, SliceWriter, Tagged, Writer}; 4 use core::marker::PhantomData; 5 6 #[cfg(feature = "alloc")] 7 use {alloc::boxed::Box, alloc::vec::Vec, core::iter}; 8 9 #[cfg(feature = "pem")] 10 use { 11 crate::PemWriter, 12 alloc::string::String, 13 pem_rfc7468::{self as pem, LineEnding, PemLabel}, 14 }; 15 16 #[cfg(any(feature = "alloc", feature = "pem"))] 17 use crate::ErrorKind; 18 19 #[cfg(doc)] 20 use crate::Tag; 21 22 /// Encoding trait. 23 pub trait Encode { 24 /// Compute the length of this value in bytes when encoded as ASN.1 DER. encoded_len(&self) -> Result<Length>25 fn encoded_len(&self) -> Result<Length>; 26 27 /// Encode this value as ASN.1 DER using the provided [`Writer`]. encode(&self, encoder: &mut impl Writer) -> Result<()>28 fn encode(&self, encoder: &mut impl Writer) -> Result<()>; 29 30 /// Encode this value to the provided byte slice, returning a sub-slice 31 /// containing the encoded message. encode_to_slice<'a>(&self, buf: &'a mut [u8]) -> Result<&'a [u8]>32 fn encode_to_slice<'a>(&self, buf: &'a mut [u8]) -> Result<&'a [u8]> { 33 let mut writer = SliceWriter::new(buf); 34 self.encode(&mut writer)?; 35 writer.finish() 36 } 37 38 /// Encode this message as ASN.1 DER, appending it to the provided 39 /// byte vector. 40 #[cfg(feature = "alloc")] encode_to_vec(&self, buf: &mut Vec<u8>) -> Result<Length>41 fn encode_to_vec(&self, buf: &mut Vec<u8>) -> Result<Length> { 42 let expected_len = usize::try_from(self.encoded_len()?)?; 43 buf.reserve(expected_len); 44 buf.extend(iter::repeat(0).take(expected_len)); 45 46 let mut writer = SliceWriter::new(buf); 47 self.encode(&mut writer)?; 48 let actual_len = writer.finish()?.len(); 49 50 if expected_len != actual_len { 51 return Err(ErrorKind::Incomplete { 52 expected_len: expected_len.try_into()?, 53 actual_len: actual_len.try_into()?, 54 } 55 .into()); 56 } 57 58 actual_len.try_into() 59 } 60 61 /// Encode this type as DER, returning a byte vector. 62 #[cfg(feature = "alloc")] to_der(&self) -> Result<Vec<u8>>63 fn to_der(&self) -> Result<Vec<u8>> { 64 let mut buf = Vec::new(); 65 self.encode_to_vec(&mut buf)?; 66 Ok(buf) 67 } 68 } 69 70 impl<T> Encode for T 71 where 72 T: EncodeValue + Tagged, 73 { 74 /// Compute the length of this value in bytes when encoded as ASN.1 DER. encoded_len(&self) -> Result<Length>75 fn encoded_len(&self) -> Result<Length> { 76 self.value_len().and_then(|len| len.for_tlv()) 77 } 78 79 /// Encode this value as ASN.1 DER using the provided [`Writer`]. encode(&self, writer: &mut impl Writer) -> Result<()>80 fn encode(&self, writer: &mut impl Writer) -> Result<()> { 81 self.header()?.encode(writer)?; 82 self.encode_value(writer) 83 } 84 } 85 86 /// Dummy implementation for [`PhantomData`] which allows deriving 87 /// implementations on structs with phantom fields. 88 impl<T> Encode for PhantomData<T> 89 where 90 T: ?Sized, 91 { encoded_len(&self) -> Result<Length>92 fn encoded_len(&self) -> Result<Length> { 93 Ok(Length::ZERO) 94 } 95 encode(&self, _writer: &mut impl Writer) -> Result<()>96 fn encode(&self, _writer: &mut impl Writer) -> Result<()> { 97 Ok(()) 98 } 99 } 100 101 /// PEM encoding trait. 102 /// 103 /// This trait is automatically impl'd for any type which impls both 104 /// [`Encode`] and [`PemLabel`]. 105 #[cfg(feature = "pem")] 106 pub trait EncodePem: Encode + PemLabel { 107 /// Try to encode this type as PEM. to_pem(&self, line_ending: LineEnding) -> Result<String>108 fn to_pem(&self, line_ending: LineEnding) -> Result<String>; 109 } 110 111 #[cfg(feature = "pem")] 112 impl<T: Encode + PemLabel> EncodePem for T { to_pem(&self, line_ending: LineEnding) -> Result<String>113 fn to_pem(&self, line_ending: LineEnding) -> Result<String> { 114 let der_len = usize::try_from(self.encoded_len()?)?; 115 let pem_len = pem::encapsulated_len(Self::PEM_LABEL, line_ending, der_len)?; 116 117 let mut buf = vec![0u8; pem_len]; 118 let mut writer = PemWriter::new(Self::PEM_LABEL, line_ending, &mut buf)?; 119 self.encode(&mut writer)?; 120 121 let actual_len = writer.finish()?; 122 buf.truncate(actual_len); 123 Ok(String::from_utf8(buf)?) 124 } 125 } 126 127 /// Encode the value part of a Tag-Length-Value encoded field, sans the [`Tag`] 128 /// and [`Length`]. 129 pub trait EncodeValue { 130 /// Get the [`Header`] used to encode this value. header(&self) -> Result<Header> where Self: Tagged,131 fn header(&self) -> Result<Header> 132 where 133 Self: Tagged, 134 { 135 Header::new(self.tag(), self.value_len()?) 136 } 137 138 /// Compute the length of this value (sans [`Tag`]+[`Length`] header) when 139 /// encoded as ASN.1 DER. value_len(&self) -> Result<Length>140 fn value_len(&self) -> Result<Length>; 141 142 /// Encode value (sans [`Tag`]+[`Length`] header) as ASN.1 DER using the 143 /// provided [`Writer`]. encode_value(&self, encoder: &mut impl Writer) -> Result<()>144 fn encode_value(&self, encoder: &mut impl Writer) -> Result<()>; 145 } 146 147 #[cfg(feature = "alloc")] 148 impl<T> EncodeValue for Box<T> 149 where 150 T: EncodeValue, 151 { value_len(&self) -> Result<Length>152 fn value_len(&self) -> Result<Length> { 153 T::value_len(self) 154 } encode_value(&self, writer: &mut impl Writer) -> Result<()>155 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { 156 T::encode_value(self, writer) 157 } 158 } 159