• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Streaming PEM reader.
2 
3 use super::Reader;
4 use crate::{ErrorKind, Header, Length, Result};
5 use pem_rfc7468::Decoder;
6 
7 /// `Reader` type which decodes PEM on-the-fly.
8 #[cfg(feature = "pem")]
9 #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
10 #[derive(Clone)]
11 pub struct PemReader<'i> {
12     /// Inner PEM decoder.
13     decoder: Decoder<'i>,
14 
15     /// Input length (in bytes after Base64 decoding).
16     input_len: Length,
17 
18     /// Position in the input buffer (in bytes after Base64 decoding).
19     position: Length,
20 }
21 
22 #[cfg(feature = "pem")]
23 #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
24 impl<'i> PemReader<'i> {
25     /// Create a new PEM reader which decodes data on-the-fly.
26     ///
27     /// Uses the default 64-character line wrapping.
new(pem: &'i [u8]) -> Result<Self>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             input_len,
35             position: Length::ZERO,
36         })
37     }
38 
39     /// Get the PEM label which will be used in the encapsulation boundaries
40     /// for this document.
type_label(&self) -> &'i str41     pub fn type_label(&self) -> &'i str {
42         self.decoder.type_label()
43     }
44 }
45 
46 #[cfg(feature = "pem")]
47 #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
48 impl<'i> Reader<'i> for PemReader<'i> {
input_len(&self) -> Length49     fn input_len(&self) -> Length {
50         self.input_len
51     }
52 
peek_byte(&self) -> Option<u8>53     fn peek_byte(&self) -> Option<u8> {
54         // TODO(tarcieri): lookahead buffer
55         None
56     }
57 
peek_header(&self) -> Result<Header>58     fn peek_header(&self) -> Result<Header> {
59         // TODO(tarcieri): lookahead buffer
60         Err(ErrorKind::Reader.into())
61     }
62 
position(&self) -> Length63     fn position(&self) -> Length {
64         self.position
65     }
66 
read_slice(&mut self, _len: Length) -> Result<&'i [u8]>67     fn read_slice(&mut self, _len: Length) -> Result<&'i [u8]> {
68         // Can't borrow from PEM because it requires decoding
69         Err(ErrorKind::Reader.into())
70     }
71 
read_into<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]>72     fn read_into<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]> {
73         let bytes = self.decoder.decode(buf)?;
74         self.position = (self.position + bytes.len())?;
75 
76         debug_assert_eq!(
77             self.position,
78             (self.input_len - Length::try_from(self.decoder.remaining_len())?)?
79         );
80 
81         Ok(bytes)
82     }
83 }
84