From b838d4b1bfc4b432e908741c94b336df19d201ad Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Mon, 15 Jan 2024 18:35:00 +0100 Subject: openpgp: Add Parse::from_buffered_reader. - Add a buffered-reader-based function to trait Parse. This allows us to manipulate the buffered reader stack before and after parsing, e.g. to parse several armored objects in one stream. The CertParser also does this, but uses internal interfaces for that. --- openpgp/src/parse.rs | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) (limited to 'openpgp/src/parse.rs') diff --git a/openpgp/src/parse.rs b/openpgp/src/parse.rs index 1b2333a0..b731b74e 100644 --- a/openpgp/src/parse.rs +++ b/openpgp/src/parse.rs @@ -281,6 +281,20 @@ pub(crate) const RECOVERY_THRESHOLD: usize = 32 * 1024; /// This is a uniform interface to parse packets, messages, keys, and /// related data structures. pub trait Parse<'a, T> { + /// Reads from the given buffered reader. + fn from_buffered_reader(reader: R) -> Result + where + R: BufferedReader + 'a, + { + // XXXv2: Make this function the mandatory one instead of + // Parse::from_reader. + + // Currently, we express the default implementation over + // Self::from_reader, which is no worse than using from_reader + // directly. + Self::from_reader(reader) + } + /// Reads from the given reader. fn from_reader(reader: R) -> Result; @@ -338,15 +352,14 @@ macro_rules! impl_parse_with_buffered_reader { // from_buffered_reader should be a closure that takes a // BufferedReader and returns a Result. ($typ: ident, $from_buffered_reader: expr) => { - impl $typ { - fn from_buffered_reader<'a, B>(br: B) -> Result - where B: 'a + BufferedReader, + impl<'a> Parse<'a, $typ> for $typ { + fn from_buffered_reader(reader: R) -> Result + where + R: BufferedReader + 'a, { - Ok($from_buffered_reader(br.into_boxed())?) + Ok($from_buffered_reader(reader.into_boxed())?) } - } - impl<'a> Parse<'a, $typ> for $typ { fn from_reader(reader: R) -> Result { let br = buffered_reader::Generic::with_cookie( reader, None, Cookie::default()); @@ -3222,10 +3235,11 @@ impl_parse_with_buffered_reader!( }) }); -impl<'a> Parse<'a, Packet> for Packet { - fn from_reader(reader: R) -> Result { +impl_parse_with_buffered_reader!( + Packet, + |br| -> Result { let ppr = - PacketParserBuilder::from_reader(reader) + PacketParserBuilder::from_buffered_reader(br) ?.buffer_unread_content().build()?; let (p, ppr) = match ppr { @@ -3244,8 +3258,7 @@ impl<'a> Parse<'a, Packet> for Packet { Err(Error::InvalidOperation( "Excess data after packet".into()).into()), } - } -} + }); // State that lives for the life of the packet parser, not the life of // an individual packet. @@ -3968,6 +3981,17 @@ impl<'a> PacketParserResult<'a> { } impl<'a> Parse<'a, PacketParserResult<'a>> for PacketParser<'a> { + /// Starts parsing an OpenPGP object stored in a `BufferedReader` object. + /// + /// This function returns a `PacketParser` for the first packet in + /// the stream. + fn from_buffered_reader(reader: R) -> Result> + where + R: BufferedReader + 'a, + { + PacketParserBuilder::from_buffered_reader(reader)?.build() + } + /// Starts parsing an OpenPGP message stored in a `std::io::Read` object. /// /// This function returns a `PacketParser` for the first packet in -- cgit v1.2.3