diff options
-rw-r--r-- | openpgp/NEWS | 2 | ||||
-rw-r--r-- | openpgp/src/armor.rs | 9 | ||||
-rw-r--r-- | openpgp/src/cert.rs | 17 | ||||
-rw-r--r-- | openpgp/src/cert/parser/mod.rs | 10 | ||||
-rw-r--r-- | openpgp/src/cert/raw.rs | 23 | ||||
-rw-r--r-- | openpgp/src/message/mod.rs | 16 | ||||
-rw-r--r-- | openpgp/src/packet_pile.rs | 11 | ||||
-rw-r--r-- | openpgp/src/parse.rs | 46 | ||||
-rw-r--r-- | openpgp/src/parse/packet_parser_builder.rs | 11 | ||||
-rw-r--r-- | openpgp/src/parse/packet_pile_parser.rs | 7 | ||||
-rw-r--r-- | openpgp/src/parse/stream.rs | 21 |
11 files changed, 158 insertions, 15 deletions
diff --git a/openpgp/NEWS b/openpgp/NEWS index f694f869..1aac12d3 100644 --- a/openpgp/NEWS +++ b/openpgp/NEWS @@ -12,6 +12,8 @@ - KeyAmalgamation::active_certifications_by_key - UserIDAmalgamation::valid_third_party_revocations_by_key - KeyAmalgamation::valid_third_party_revocations_by_key + - Parse::from_buffered_reader + - armor::Reader::from_buffered_reader * Changes in 1.17.0 ** Notable fixes - Sequoia now ignores some formatting errors when reading secret diff --git a/openpgp/src/armor.rs b/openpgp/src/armor.rs index 97e82d1e..992977b7 100644 --- a/openpgp/src/armor.rs +++ b/openpgp/src/armor.rs @@ -627,6 +627,15 @@ impl<'a> Reader<'a> { mode, Default::default()) } + /// Constructs a new `Reader` from the given `BufferedReader`. + pub fn from_buffered_reader<R, M>(reader: R, mode: M) -> Result<Self> + where + R: BufferedReader<Cookie> + 'a, + M: Into<Option<ReaderMode>>, + { + Ok(Self::from_cookie_reader(reader.into_boxed(), mode, Default::default())) + } + /// Constructs a new `Reader` from the given `io::Read`er. /// /// [ASCII Armor], designed to protect OpenPGP data in transit, diff --git a/openpgp/src/cert.rs b/openpgp/src/cert.rs index 9c8a1869..81a05c5d 100644 --- a/openpgp/src/cert.rs +++ b/openpgp/src/cert.rs @@ -141,6 +141,8 @@ use std::fmt; use std::ops::{Deref, DerefMut}; use std::time; +use buffered_reader::BufferedReader; + use crate::{ crypto::{ Signer, @@ -165,7 +167,7 @@ use crate::{ KeyHandle, policy::Policy, }; -use crate::parse::{Parse, PacketParserResult, PacketParser}; +use crate::parse::{Cookie, Parse, PacketParserResult, PacketParser}; use crate::types::{ AEADAlgorithm, CompressionAlgorithm, @@ -775,6 +777,19 @@ impl<'a> Parse<'a, Cert> for Cert { /// /// If `reader` contains multiple certificates, this returns an /// error. Use [`CertParser`] if you want to parse a keyring. + fn from_buffered_reader<R>(reader: R) -> Result<Cert> + where + R: BufferedReader<Cookie> + 'a, + { + Cert::try_from(PacketParser::from_buffered_reader(reader)?) + } + + /// Parses and returns a certificate. + /// + /// The reader must return an OpenPGP-encoded certificate. + /// + /// If `reader` contains multiple certificates, this returns an + /// error. Use [`CertParser`] if you want to parse a keyring. fn from_reader<R: io::Read + Send + Sync>(reader: R) -> Result<Self> { Cert::try_from(PacketParser::from_reader(reader)?) } diff --git a/openpgp/src/cert/parser/mod.rs b/openpgp/src/cert/parser/mod.rs index 147f32de..e8963d94 100644 --- a/openpgp/src/cert/parser/mod.rs +++ b/openpgp/src/cert/parser/mod.rs @@ -3,6 +3,7 @@ use std::mem; use std::vec; use std::path::Path; +use buffered_reader::BufferedReader; use lalrpop_util::ParseError; use crate::{ @@ -11,6 +12,7 @@ use crate::{ packet::Tag, Packet, parse::{ + Cookie, Parse, PacketParserResult, PacketParser @@ -594,6 +596,14 @@ impl<'a> From<Vec<Packet>> for CertParser<'a> { impl<'a> Parse<'a, CertParser<'a>> for CertParser<'a> { + /// Initializes a `CertParser` from a `BufferedReader`. + fn from_buffered_reader<R>(reader: R) -> Result<CertParser<'a>> + where + R: BufferedReader<Cookie> + 'a, + { + Ok(Self::from(PacketParser::from_buffered_reader(reader)?)) + } + /// Initializes a `CertParser` from a `Read`er. fn from_reader<R: 'a + io::Read + Send + Sync>(reader: R) -> Result<Self> { Ok(Self::from(PacketParser::from_reader(reader)?)) diff --git a/openpgp/src/cert/raw.rs b/openpgp/src/cert/raw.rs index e9610818..bd981c24 100644 --- a/openpgp/src/cert/raw.rs +++ b/openpgp/src/cert/raw.rs @@ -459,8 +459,11 @@ impl<'a> Parse<'a, RawCert<'a>> for RawCert<'a> { /// Returns the first RawCert encountered in the reader. /// /// Returns an error if there are multiple certificates. - fn from_reader<R: 'a + Read + Send + Sync>(reader: R) -> Result<Self> { - let mut parser = RawCertParser::from_reader(reader)?; + fn from_buffered_reader<R>(reader: R) -> Result<RawCert<'a>> + where + R: BufferedReader<Cookie> + 'a + { + let mut parser = RawCertParser::from_buffered_reader(reader)?; if let Some(cert_result) = parser.next() { if parser.next().is_some() { Err(Error::MalformedCert( @@ -473,6 +476,14 @@ impl<'a> Parse<'a, RawCert<'a>> for RawCert<'a> { Err(Error::MalformedCert("No data".into()).into()) } } + + /// Returns the first RawCert encountered in the reader. + /// + /// Returns an error if there are multiple certificates. + fn from_reader<R: 'a + Read + Send + Sync>(reader: R) -> Result<Self> { + let br = Generic::with_cookie(reader, None, Cookie::default()); + Self::from_buffered_reader(br) + } } impl<'a> crate::seal::Sealed for RawCert<'a> {} @@ -655,6 +666,14 @@ impl<'a> RawCertParser<'a> { impl<'a> Parse<'a, RawCertParser<'a>> for RawCertParser<'a> { + /// Initializes a `RawCertParser` from a `BufferedReader`. + fn from_buffered_reader<R>(reader: R) -> Result<RawCertParser<'a>> + where + R: BufferedReader<Cookie> + 'a + { + RawCertParser::new(reader) + } + /// Initializes a `RawCertParser` from a `Read`er. fn from_reader<R: 'a + Read + Send + Sync>(reader: R) -> Result<Self> { RawCertParser::new(Generic::with_cookie(reader, None, Default::default())) diff --git a/openpgp/src/message/mod.rs b/openpgp/src/message/mod.rs index 5a9d3b1f..d6da5a8f 100644 --- a/openpgp/src/message/mod.rs +++ b/openpgp/src/message/mod.rs @@ -29,13 +29,15 @@ use std::fmt; use std::io; use std::path::Path; +use buffered_reader::BufferedReader; + use crate::Result; use crate::Error; use crate::Packet; use crate::PacketPile; use crate::packet::Literal; use crate::packet::Tag; -use crate::parse::Parse; +use crate::parse::{Cookie, Parse}; mod lexer; lalrpop_util::lalrpop_mod!(#[allow(clippy::all, deprecated)] grammar, "/message/grammar.rs"); @@ -348,6 +350,18 @@ impl<'a> Parse<'a, Message> for Message { /// See [`Message::try_from`] for more details. /// /// [`Message::try_from`]: Message::try_from() + fn from_buffered_reader<R>(reader: R) -> Result<Message> + where + R: BufferedReader<Cookie> + 'a, + { + Self::try_from(PacketPile::from_buffered_reader(reader)?) + } + + /// Reads a `Message` from the specified reader. + /// + /// See [`Message::try_from`] for more details. + /// + /// [`Message::try_from`]: Message::try_from() fn from_reader<R: 'a + io::Read + Send + Sync>(reader: R) -> Result<Self> { Self::try_from(PacketPile::from_reader(reader)?) } diff --git a/openpgp/src/packet_pile.rs b/openpgp/src/packet_pile.rs index f62eb6f6..1678c523 100644 --- a/openpgp/src/packet_pile.rs +++ b/openpgp/src/packet_pile.rs @@ -120,6 +120,17 @@ impl fmt::Debug for PacketPile { } impl<'a> Parse<'a, PacketPile> for PacketPile { + /// Deserializes the OpenPGP message stored in the file named by + /// `path`. + /// + /// See `from_reader` for more details and caveats. + fn from_buffered_reader<R>(reader: R) -> Result<PacketPile> + where + R: BufferedReader<Cookie> + 'a, + { + PacketPile::from_cookie_reader(reader.into_boxed()) + } + /// Deserializes the OpenPGP message stored in a `std::io::Read` /// object. /// 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<R>(reader: R) -> Result<T> + where + R: BufferedReader<Cookie> + '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<R: 'a + Read + Send + Sync>(reader: R) -> Result<T>; @@ -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<Self>. ($typ: ident, $from_buffered_reader: expr) => { - impl $typ { - fn from_buffered_reader<'a, B>(br: B) -> Result<Self> - where B: 'a + BufferedReader<Cookie>, + impl<'a> Parse<'a, $typ> for $typ { + fn from_buffered_reader<R>(reader: R) -> Result<Self> + where + R: BufferedReader<Cookie> + '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<R: 'a + Read + Send + Sync>(reader: R) -> Result<Self> { 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<R: 'a + Read + Send + Sync>(reader: R) -> Result<Self> { +impl_parse_with_buffered_reader!( + Packet, + |br| -> Result<Self> { 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<R>(reader: R) -> Result<PacketParserResult<'a>> + where + R: BufferedReader<Cookie> + '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 diff --git a/openpgp/src/parse/packet_parser_builder.rs b/openpgp/src/parse/packet_parser_builder.rs index 02a83ad3..2b52efd5 100644 --- a/openpgp/src/parse/packet_parser_builder.rs +++ b/openpgp/src/parse/packet_parser_builder.rs @@ -99,6 +99,17 @@ pub struct PacketParserBuilder<'a> { assert_send_and_sync!(PacketParserBuilder<'_>); impl<'a> Parse<'a, PacketParserBuilder<'a>> for PacketParserBuilder<'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<R>(reader: R) -> Result<PacketParserBuilder<'a>> + where + R: BufferedReader<Cookie> + 'a, + { + PacketParserBuilder::from_cookie_reader(reader.into_boxed()) + } + /// Creates a `PacketParserBuilder` for an OpenPGP message stored /// in a `std::io::Read` object. fn from_reader<R: io::Read + 'a + Send + Sync>(reader: R) -> Result<Self> { diff --git a/openpgp/src/parse/packet_pile_parser.rs b/openpgp/src/parse/packet_pile_parser.rs index ea65912e..b06cf6d8 100644 --- a/openpgp/src/parse/packet_pile_parser.rs +++ b/openpgp/src/parse/packet_pile_parser.rs @@ -218,6 +218,13 @@ impl<'a> TryFrom<PacketParserBuilder<'a>> for PacketPileParser<'a> { } impl<'a> Parse<'a, PacketPileParser<'a>> for PacketPileParser<'a> { + fn from_buffered_reader<R>(reader: R) -> Result<PacketPileParser<'a>> + where + R: BufferedReader<Cookie> + 'a + { + PacketPileParser::from_cookie_reader(reader.into_boxed()) + } + /// Creates a `PacketPileParser` to parse the OpenPGP message stored /// in the `io::Read` object. fn from_reader<R: io::Read + 'a + Send + Sync>(reader: R) diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs index 288df6ac..63d42507 100644 --- a/openpgp/src/parse/stream.rs +++ b/openpgp/src/parse/stream.rs @@ -1059,6 +1059,13 @@ assert_send_and_sync!(VerifierBuilder<'_>); impl<'a> Parse<'a, VerifierBuilder<'a>> for VerifierBuilder<'a> { + fn from_buffered_reader<R>(reader: R) -> Result<VerifierBuilder<'a>> + where + R: BufferedReader<Cookie> + 'a, + { + VerifierBuilder::new(reader) + } + fn from_reader<R>(reader: R) -> Result<VerifierBuilder<'a>> where R: io::Read + 'a + Send + Sync, { @@ -1460,6 +1467,13 @@ assert_send_and_sync!(DetachedVerifierBuilder<'_>); impl<'a> Parse<'a, DetachedVerifierBuilder<'a>> for DetachedVerifierBuilder<'a> { + fn from_buffered_reader<R>(reader: R) -> Result<DetachedVerifierBuilder<'a>> + where + R: BufferedReader<Cookie> + 'a, + { + DetachedVerifierBuilder::new(reader) + } + fn from_reader<R>(reader: R) -> Result<DetachedVerifierBuilder<'a>> where R: io::Read + 'a + Send + Sync, { @@ -1817,6 +1831,13 @@ assert_send_and_sync!(DecryptorBuilder<'_>); impl<'a> Parse<'a, DecryptorBuilder<'a>> for DecryptorBuilder<'a> { + fn from_buffered_reader<R>(reader: R) -> Result<DecryptorBuilder<'a>> + where + R: BufferedReader<Cookie> + 'a, + { + DecryptorBuilder::new(reader) + } + fn from_reader<R>(reader: R) -> Result<DecryptorBuilder<'a>> where R: io::Read + 'a + Send + Sync, { |