der/
encode.rs

1//! Trait definition for [`Encode`].
2
3use crate::{Header, Length, Result, SliceWriter, Tagged, Writer};
4
5#[cfg(feature = "alloc")]
6use {alloc::vec::Vec, core::iter};
7
8#[cfg(feature = "pem")]
9use {
10    crate::PemWriter,
11    alloc::string::String,
12    pem_rfc7468::{self as pem, LineEnding, PemLabel},
13};
14
15#[cfg(any(feature = "alloc", feature = "pem"))]
16use crate::ErrorKind;
17
18#[cfg(doc)]
19use crate::Tag;
20
21/// Encoding trait.
22pub trait Encode {
23    /// Compute the length of this value in bytes when encoded as ASN.1 DER.
24    fn encoded_len(&self) -> Result<Length>;
25
26    /// Encode this value as ASN.1 DER using the provided [`Writer`].
27    fn encode(&self, encoder: &mut dyn Writer) -> Result<()>;
28
29    /// Encode this value to the provided byte slice, returning a sub-slice
30    /// containing the encoded message.
31    fn encode_to_slice<'a>(&self, buf: &'a mut [u8]) -> Result<&'a [u8]> {
32        let mut writer = SliceWriter::new(buf);
33        self.encode(&mut writer)?;
34        writer.finish()
35    }
36
37    /// Encode this message as ASN.1 DER, appending it to the provided
38    /// byte vector.
39    #[cfg(feature = "alloc")]
40    #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
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    /// Serialize this message as a byte vector.
62    #[cfg(feature = "alloc")]
63    #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
64    fn to_vec(&self) -> Result<Vec<u8>> {
65        let mut buf = Vec::new();
66        self.encode_to_vec(&mut buf)?;
67        Ok(buf)
68    }
69}
70
71impl<T> Encode for T
72where
73    T: EncodeValue + Tagged,
74{
75    /// Compute the length of this value in bytes when encoded as ASN.1 DER.
76    fn encoded_len(&self) -> Result<Length> {
77        self.value_len().and_then(|len| len.for_tlv())
78    }
79
80    /// Encode this value as ASN.1 DER using the provided [`Writer`].
81    fn encode(&self, writer: &mut dyn Writer) -> Result<()> {
82        self.header()?.encode(writer)?;
83        self.encode_value(writer)
84    }
85}
86
87/// PEM encoding trait.
88///
89/// This trait is automatically impl'd for any type which impls both
90/// [`Encode`] and [`PemLabel`].
91#[cfg(feature = "pem")]
92#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
93pub trait EncodePem: Encode + PemLabel {
94    /// Try to encode this type as PEM.
95    fn to_pem(&self, line_ending: LineEnding) -> Result<String>;
96}
97
98#[cfg(feature = "pem")]
99#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
100impl<T: Encode + PemLabel> EncodePem for T {
101    fn to_pem(&self, line_ending: LineEnding) -> Result<String> {
102        let der_len = usize::try_from(self.encoded_len()?)?;
103        let pem_len = pem::encapsulated_len(Self::PEM_LABEL, line_ending, der_len)?;
104
105        let mut buf = vec![0u8; pem_len];
106        let mut writer = PemWriter::new(Self::PEM_LABEL, line_ending, &mut buf)?;
107        self.encode(&mut writer)?;
108
109        let actual_len = writer.finish()?;
110        buf.truncate(actual_len);
111        Ok(String::from_utf8(buf)?)
112    }
113}
114
115/// Encode the value part of a Tag-Length-Value encoded field, sans the [`Tag`]
116/// and [`Length`].
117pub trait EncodeValue {
118    /// Get the [`Header`] used to encode this value.
119    fn header(&self) -> Result<Header>
120    where
121        Self: Tagged,
122    {
123        Header::new(self.tag(), self.value_len()?)
124    }
125
126    /// Compute the length of this value (sans [`Tag`]+[`Length`] header) when
127    /// encoded as ASN.1 DER.
128    fn value_len(&self) -> Result<Length>;
129
130    /// Encode value (sans [`Tag`]+[`Length`] header) as ASN.1 DER using the
131    /// provided [`Writer`].
132    fn encode_value(&self, encoder: &mut dyn Writer) -> Result<()>;
133}