diff options
author | Neal H. Walfield <neal@pep.foundation> | 2019-11-07 11:48:23 +0100 |
---|---|---|
committer | Neal H. Walfield <neal@pep.foundation> | 2019-11-07 12:04:51 +0100 |
commit | 5bbd9b88f6c49f7e22a6bc817b8bdf251565f460 (patch) | |
tree | 60f994707b87fc919c85040ef6fce5ddf3e6b4c3 /openpgp/src/parse | |
parent | ec1063a3c684b5c44886907b2a9817ff2e557be7 (diff) |
openpgp: Use a Vec instead of a HashMap.
- A SignatureGroup currently contains a hash mapping hash algorithms
to hash contexts. Typically this will only contain one or two
mappings. At most it will contain one mapping for each algorithm
that we support (currently, we support 7 hash algorithms).
- Given the small expected and small maximum size, a vector is the
better data structure:
- The small number of elements means that look up time will be
comparable whether we do a linear scan or look in a hash (in
fact, the linear scan is probably cache friendlier).
- Iterating over a vector is faster than iterating over a hash
map. The is the fast path.
- A vector takes up less space.
- Change SignatureGroup::hashes to use a Vec instead of a HashMap.
Diffstat (limited to 'openpgp/src/parse')
-rw-r--r-- | openpgp/src/parse/hashed_reader.rs | 3 | ||||
-rw-r--r-- | openpgp/src/parse/parse.rs | 27 |
2 files changed, 20 insertions, 10 deletions
diff --git a/openpgp/src/parse/hashed_reader.rs b/openpgp/src/parse/hashed_reader.rs index ff1f77da..120cf222 100644 --- a/openpgp/src/parse/hashed_reader.rs +++ b/openpgp/src/parse/hashed_reader.rs @@ -39,7 +39,8 @@ impl<R: BufferedReader<Cookie>> HashedReader<R> { -> Self { let mut cookie = Cookie::default(); for &algo in &algos { - cookie.sig_group_mut().hashes.insert(algo, algo.context().unwrap()); + cookie.sig_group_mut().hashes + .push((algo, algo.context().unwrap())); } cookie.hashes_for = hashes_for; diff --git a/openpgp/src/parse/parse.rs b/openpgp/src/parse/parse.rs index 8541e660..06920967 100644 --- a/openpgp/src/parse/parse.rs +++ b/openpgp/src/parse/parse.rs @@ -2,7 +2,6 @@ use std; use std::io; use std::io::prelude::*; use std::cmp; -use std::collections::HashMap; use std::str; use std::mem; use std::fmt; @@ -489,12 +488,12 @@ pub(crate) struct SignatureGroup { ops_count: usize, /// Maps hash algorithms to hash contexts. - pub(crate) hashes: HashMap<HashAlgorithm, crypto::hash::Context>, + pub(crate) hashes: Vec<(HashAlgorithm, crypto::hash::Context)>, } impl fmt::Debug for SignatureGroup { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let algos = self.hashes.keys() + let algos = self.hashes.iter().map(|(a, _)| a) .collect::<Vec<&HashAlgorithm>>(); f.debug_struct("Cookie") @@ -508,7 +507,7 @@ impl Default for SignatureGroup { fn default() -> Self { SignatureGroup { ops_count: 0, - hashes: HashMap::new(), + hashes: Default::default(), } } } @@ -1051,7 +1050,12 @@ impl Signature4 { if cookie.hashes_for == HashesFor::Signature { cookie.sig_group_mut().ops_count -= 1; if let Some(hash) = - cookie.sig_group().hashes.get(&hash_algo) + cookie.sig_group().hashes.iter().find_map( + |(a, h)| if *a == hash_algo { + Some(h) + } else { + None + }) { t!("popped a {:?} HashedReader", hash_algo); computed_hash = Some((cookie.signature_level(), @@ -1224,11 +1228,11 @@ impl OnePassSig3 { // Make sure that it uses the required // hash algorithm. if ! cookie.sig_group() - .hashes.contains_key(&hash_algo) + .hashes.iter().any(|(a, _)| *a == hash_algo) { if let Ok(ctx) = hash_algo.context() { cookie.sig_group_mut() - .hashes.insert(hash_algo, ctx); + .hashes.push((hash_algo, ctx)); } } @@ -2023,8 +2027,13 @@ impl MDC { if state.hashes_for == HashesFor::MDC { if state.sig_group().hashes.len() > 0 { let h = state.sig_group_mut().hashes - .get_mut(&HashAlgorithm::SHA1) - .unwrap(); + .iter_mut().find_map( + |(a, h)| + if *a == HashAlgorithm::SHA1 { + Some(h) + } else { + None + }).unwrap(); h.digest(&mut computed_hash); } |