Skip to main content

der/reader/
pem.rs

1//! Streaming PEM reader.
2
3use super::{Reader, position::Position};
4use crate::{EncodingRules, Error, ErrorKind, Length, Result};
5use core::fmt;
6use pem_rfc7468::Decoder;
7
8/// `Reader` type which decodes PEM on-the-fly.
9#[derive(Clone)]
10pub struct PemReader<'i> {
11    /// Inner PEM decoder.
12    decoder: Decoder<'i>,
13
14    /// Encoding rules to apply when decoding the input.
15    encoding_rules: EncodingRules,
16
17    /// Position tracker.
18    position: Position,
19}
20
21impl<'i> PemReader<'i> {
22    /// Create a new PEM reader which decodes data on-the-fly.
23    ///
24    /// Uses the default 64-character line wrapping.
25    ///
26    /// # Errors
27    /// If a decoding error occurred.
28    pub fn new(pem: &'i [u8]) -> Result<Self> {
29        let decoder = Decoder::new(pem)?;
30        let input_len = Length::try_from(decoder.remaining_len())?;
31
32        Ok(Self {
33            decoder,
34            encoding_rules: EncodingRules::default(),
35            position: Position::new(input_len),
36        })
37    }
38
39    /// Get the PEM label which will be used in the encapsulation boundaries
40    /// for this document.
41    #[must_use]
42    pub fn type_label(&self) -> &'i str {
43        self.decoder.type_label()
44    }
45}
46
47impl<'i> Reader<'static> for PemReader<'i> {
48    const CAN_READ_SLICE: bool = false;
49
50    fn encoding_rules(&self) -> EncodingRules {
51        self.encoding_rules
52    }
53
54    fn input_len(&self) -> Length {
55        self.position.input_len()
56    }
57
58    fn position(&self) -> Length {
59        self.position.current()
60    }
61
62    fn read_nested<T, F, E>(&mut self, len: Length, f: F) -> core::result::Result<T, E>
63    where
64        F: FnOnce(&mut Self) -> core::result::Result<T, E>,
65        E: From<Error>,
66    {
67        let resumption = self.position.split_nested(len)?;
68        let ret = f(self);
69        self.position.resume_nested(resumption);
70        ret
71    }
72
73    fn read_slice(&mut self, _len: Length) -> Result<&'static [u8]> {
74        // Can't borrow from PEM because it requires decoding
75        Err(self.error(ErrorKind::Reader))
76    }
77
78    fn read_into<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]> {
79        self.position.advance(Length::try_from(buf.len())?)?;
80        self.decoder.decode(buf)?;
81        Ok(buf)
82    }
83}
84
85impl fmt::Debug for PemReader<'_> {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        f.debug_struct("PemReader")
88            .field("position", &self.position)
89            .field("encoding_rules", &self.encoding_rules)
90            .finish_non_exhaustive()
91    }
92}