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