ssh_encoding/pem/
encode.rs

1use super::{LineEnding, PemLabel, writer::PemWriter};
2use crate::{Encode, Error};
3use core::str;
4
5#[cfg(feature = "alloc")]
6use {super::LINE_WIDTH, alloc::string::String};
7
8/// Encoding trait for PEM documents.
9///
10/// This is an extension trait which is auto-impl'd for types which impl the
11/// [`Encode`] and [`PemLabel`] traits.
12pub trait EncodePem: Encode + PemLabel {
13    /// Encode this type using the [`Encode`] trait, writing the resulting PEM
14    /// document into the provided `out` buffer.
15    fn encode_pem<'o>(&self, line_ending: LineEnding, out: &'o mut [u8]) -> Result<&'o str, Error>;
16
17    /// Encode this type using the [`Encode`] trait, writing the resulting PEM
18    /// document to a returned [`String`].
19    #[cfg(feature = "alloc")]
20    fn encode_pem_string(&self, line_ending: LineEnding) -> Result<String, Error>;
21}
22
23impl<T: Encode + PemLabel> EncodePem for T {
24    fn encode_pem<'o>(&self, line_ending: LineEnding, out: &'o mut [u8]) -> Result<&'o str, Error> {
25        let mut writer = PemWriter::new(Self::PEM_LABEL, line_ending, out)?;
26        self.encode(&mut writer)?;
27
28        let encoded_len = writer.finish()?;
29        str::from_utf8(&out[..encoded_len]).map_err(Error::from)
30    }
31
32    #[cfg(feature = "alloc")]
33    fn encode_pem_string(&self, line_ending: LineEnding) -> Result<String, Error> {
34        let encoded_len = pem_rfc7468::encapsulated_len_wrapped(
35            Self::PEM_LABEL,
36            LINE_WIDTH,
37            line_ending,
38            self.encoded_len()?,
39        )
40        .map_err(Error::from)?;
41
42        let mut buf = vec![0u8; encoded_len];
43        let actual_len = self.encode_pem(line_ending, &mut buf)?.len();
44        buf.truncate(actual_len);
45        String::from_utf8(buf).map_err(Error::from)
46    }
47}