summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2021-11-03 16:54:31 +0100
committerJustus Winter <justus@sequoia-pgp.org>2021-11-03 16:54:31 +0100
commit626652afde60a4d064c912ed2a75034059ae7d02 (patch)
treec9f1d8cd541c445c7a378082caff0bd6b5ad19f0
parentfc6aee27f21f94eeecd3b495f0f45ffaa2203579 (diff)
openpgp: Try to get back on the happy path.
- If the opportunity arises, i.e. we have a buffer but previous reads exhausted it, we can drop the buffer and serve the requests from the next buffered reader without copying them first.
-rw-r--r--openpgp/src/parse/partial_body.rs21
1 files changed, 16 insertions, 5 deletions
diff --git a/openpgp/src/parse/partial_body.rs b/openpgp/src/parse/partial_body.rs
index 896d5555..1bd4e863 100644
--- a/openpgp/src/parse/partial_body.rs
+++ b/openpgp/src/parse/partial_body.rs
@@ -32,8 +32,8 @@ pub(crate) struct BufferedReaderPartialBodyFilter<T: BufferedReader<Cookie>> {
buffer: Option<Vec<u8>>,
// The position within the buffer.
cursor: usize,
- /// Currently unused buffer.
- unused_buffer: Option<Vec<u8>>,
+ /// Currently unused buffers.
+ unused_buffers: Vec<Vec<u8>>,
// The user-defined cookie.
cookie: Cookie,
@@ -81,7 +81,7 @@ impl<T: BufferedReader<Cookie>> BufferedReaderPartialBodyFilter<T> {
last: false,
buffer: None,
cursor: 0,
- unused_buffer: None,
+ unused_buffers: Vec::with_capacity(2),
cookie,
hash_headers,
}
@@ -97,7 +97,7 @@ impl<T: BufferedReader<Cookie>> BufferedReaderPartialBodyFilter<T> {
// We want to avoid double buffering as much as possible.
// Thus, we only buffer as much as needed.
- let mut buffer = self.unused_buffer.take()
+ let mut buffer = self.unused_buffers.pop()
.map(|mut v| {
vec_resize(&mut v, amount);
v
@@ -217,7 +217,9 @@ impl<T: BufferedReader<Cookie>> BufferedReaderPartialBodyFilter<T> {
// We're done.
- self.unused_buffer = self.buffer.take();
+ if let Some(b) = self.buffer.take() {
+ self.unused_buffers.push(b);
+ }
self.buffer = Some(buffer);
self.cursor = 0;
@@ -234,6 +236,15 @@ impl<T: BufferedReader<Cookie>> BufferedReaderPartialBodyFilter<T> {
//println!("BufferedReaderPartialBodyFilter::data_helper({})", amount);
+ if self.buffer.as_ref().map(|b| b.len() == self.cursor).unwrap_or(false)
+ {
+ // We have data and it has been exhausted exactly. This
+ // is our opportunity to get back to the happy path where
+ // we don't need to double buffer.
+ self.unused_buffers.push(self.buffer.take().expect("have buffer"));
+ self.cursor = 0;
+ }
+
if let Some(ref buffer) = self.buffer {
// We have some data buffered locally.