diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
commit | 9835e2ae736235810b4ea1c162ca5e65c547e770 (patch) | |
tree | 3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/der/src/reader | |
parent | Releasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff) | |
download | rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/der/src/reader')
-rw-r--r-- | vendor/der/src/reader/pem.rs | 157 | ||||
-rw-r--r-- | vendor/der/src/reader/slice.rs | 8 |
2 files changed, 144 insertions, 21 deletions
diff --git a/vendor/der/src/reader/pem.rs b/vendor/der/src/reader/pem.rs index 01bb4f20e..f11341aa6 100644 --- a/vendor/der/src/reader/pem.rs +++ b/vendor/der/src/reader/pem.rs @@ -1,16 +1,134 @@ //! Streaming PEM reader. use super::Reader; -use crate::{ErrorKind, Header, Length, Result}; -use pem_rfc7468::Decoder; +use crate::{Decode, Error, ErrorKind, Header, Length, Result}; +use core::cell::RefCell; + +#[allow(clippy::integer_arithmetic)] +mod utils { + use crate::{Error, Length, Result}; + use pem_rfc7468::Decoder; + + #[derive(Clone)] + pub(super) struct BufReader<'i> { + /// Inner PEM decoder. + decoder: Decoder<'i>, + + /// Remaining after base64 decoding + remaining: usize, + + /// Read buffer + buf: [u8; BufReader::CAPACITY], + + /// Position of the head in the buffer, + pos: usize, + + /// Position of the tail in the buffer, + cap: usize, + } + + impl<'i> BufReader<'i> { + const CAPACITY: usize = 256; + + pub fn new(pem: &'i [u8]) -> Result<Self> { + let decoder = Decoder::new(pem)?; + let remaining = decoder.remaining_len(); + + Ok(Self { + decoder, + remaining, + buf: [0u8; 256], + pos: 0, + cap: 0, + }) + } + + pub fn remaining_len(&self) -> usize { + self.decoder.remaining_len() + self.cap - self.pos + } + + fn fill_buffer(&mut self) -> Result<()> { + debug_assert!(self.pos <= self.cap); + + if self.is_empty() { + self.pos = 0; + self.cap = 0; + } + + let end = (self.cap + self.remaining).min(Self::CAPACITY); + let writable_slice = &mut self.buf[self.cap..end]; + if writable_slice.is_empty() { + return Ok(()); + } + + let wrote = self.decoder.decode(writable_slice)?.len(); + if wrote == 0 { + return Err(Error::incomplete(Length::try_from(self.pos)?)); + } + + self.cap += wrote; + self.remaining -= wrote; + debug_assert!(self.cap <= Self::CAPACITY); + + Ok(()) + } + + /// Get the PEM label which will be used in the encapsulation boundaries + /// for this document. + pub fn type_label(&self) -> &'i str { + self.decoder.type_label() + } + + fn is_empty(&self) -> bool { + self.pos == self.cap + } + + fn as_slice(&self) -> &[u8] { + &self.buf[self.pos..self.cap] + } + } + + impl<'i> BufReader<'i> { + pub fn peek_byte(&self) -> Option<u8> { + let s = self.as_slice(); + s.first().copied() + } + + pub fn copy_to_slice<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]> { + let mut output_pos = 0; + + while output_pos < buf.len() { + if self.is_empty() { + self.fill_buffer()?; + } + + let available = &self.buf[self.pos..self.cap]; + let window_len = (buf.len() - output_pos).min(available.len()); + let window = &mut buf[output_pos..output_pos + window_len]; + + window.copy_from_slice(&available[..window_len]); + self.pos += window_len; + output_pos += window_len; + } + + // Don't leave the read buffer empty for peek_byte() + if self.is_empty() && self.decoder.remaining_len() != 0 { + self.fill_buffer()? + } + + debug_assert_eq!(output_pos, buf.len()); + + Ok(buf) + } + } +} /// `Reader` type which decodes PEM on-the-fly. #[cfg(feature = "pem")] -#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] #[derive(Clone)] pub struct PemReader<'i> { - /// Inner PEM decoder. - decoder: Decoder<'i>, + /// Inner PEM decoder wrapped in a BufReader. + reader: RefCell<utils::BufReader<'i>>, /// Input length (in bytes after Base64 decoding). input_len: Length, @@ -20,17 +138,16 @@ pub struct PemReader<'i> { } #[cfg(feature = "pem")] -#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] impl<'i> PemReader<'i> { /// Create a new PEM reader which decodes data on-the-fly. /// /// Uses the default 64-character line wrapping. pub fn new(pem: &'i [u8]) -> Result<Self> { - let decoder = Decoder::new(pem)?; - let input_len = Length::try_from(decoder.remaining_len())?; + let reader = utils::BufReader::new(pem)?; + let input_len = Length::try_from(reader.remaining_len())?; Ok(Self { - decoder, + reader: RefCell::new(reader), input_len, position: Length::ZERO, }) @@ -39,25 +156,30 @@ impl<'i> PemReader<'i> { /// Get the PEM label which will be used in the encapsulation boundaries /// for this document. pub fn type_label(&self) -> &'i str { - self.decoder.type_label() + self.reader.borrow().type_label() } } #[cfg(feature = "pem")] -#[cfg_attr(docsrs, doc(cfg(feature = "pem")))] impl<'i> Reader<'i> for PemReader<'i> { fn input_len(&self) -> Length { self.input_len } fn peek_byte(&self) -> Option<u8> { - // TODO(tarcieri): lookahead buffer - None + if self.is_finished() { + None + } else { + self.reader.borrow().peek_byte() + } } fn peek_header(&self) -> Result<Header> { - // TODO(tarcieri): lookahead buffer - Err(ErrorKind::Reader.into()) + if self.is_finished() { + Err(Error::incomplete(self.offset())) + } else { + Header::decode(&mut self.clone()) + } } fn position(&self) -> Length { @@ -70,12 +192,13 @@ impl<'i> Reader<'i> for PemReader<'i> { } fn read_into<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]> { - let bytes = self.decoder.decode(buf)?; + let bytes = self.reader.borrow_mut().copy_to_slice(buf)?; + self.position = (self.position + bytes.len())?; debug_assert_eq!( self.position, - (self.input_len - Length::try_from(self.decoder.remaining_len())?)? + (self.input_len - Length::try_from(self.reader.borrow().remaining_len())?)? ); Ok(bytes) diff --git a/vendor/der/src/reader/slice.rs b/vendor/der/src/reader/slice.rs index 6bab091f3..e78468fed 100644 --- a/vendor/der/src/reader/slice.rs +++ b/vendor/der/src/reader/slice.rs @@ -1,12 +1,12 @@ //! Slice reader. -use crate::{ByteSlice, Decode, Error, ErrorKind, Header, Length, Reader, Result, Tag}; +use crate::{BytesRef, Decode, Error, ErrorKind, Header, Length, Reader, Result, Tag}; /// [`Reader`] which consumes an input byte slice. #[derive(Clone, Debug)] pub struct SliceReader<'a> { /// Byte slice being decoded. - bytes: ByteSlice<'a>, + bytes: BytesRef<'a>, /// Did the decoding operation fail? failed: bool, @@ -19,7 +19,7 @@ impl<'a> SliceReader<'a> { /// Create a new slice reader for the given byte slice. pub fn new(bytes: &'a [u8]) -> Result<Self> { Ok(Self { - bytes: ByteSlice::new(bytes)?, + bytes: BytesRef::new(bytes)?, failed: false, position: Length::ZERO, }) @@ -64,7 +64,7 @@ impl<'a> Reader<'a> for SliceReader<'a> { fn peek_byte(&self) -> Option<u8> { self.remaining() .ok() - .and_then(|bytes| bytes.get(0).cloned()) + .and_then(|bytes| bytes.first().cloned()) } fn peek_header(&self) -> Result<Header> { |