Reimplement SignatureSet as a map so signatures can be efficiently looked up by key ID.

This commit is contained in:
Jimmy Cuadra 2019-07-09 17:01:57 -07:00
parent eaeb1a66c7
commit b85d0fc22c

View File

@ -1,7 +1,7 @@
//! Digital signatures and collections of signatures. //! Digital signatures and collections of signatures.
use std::{ use std::{
collections::{hash_map::Entry, HashMap, HashSet}, collections::{hash_map::Entry, HashMap},
error::Error as _, error::Error as _,
fmt::{Formatter, Result as FmtResult}, fmt::{Formatter, Result as FmtResult},
}; };
@ -256,14 +256,14 @@ impl<'de> Visitor<'de> for SignatureMapVisitor {
#[derive(Clone, Debug, Default, PartialEq)] #[derive(Clone, Debug, Default, PartialEq)]
pub struct SignatureSet { pub struct SignatureSet {
/// A set of signatures for a homeserver. /// A set of signatures for a homeserver.
set: HashSet<Signature>, map: HashMap<String, Signature>,
} }
impl SignatureSet { impl SignatureSet {
/// Initializes a new empty SignatureSet. /// Initializes a new empty SignatureSet.
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
set: HashSet::new(), map: HashMap::new(),
} }
} }
@ -274,25 +274,43 @@ impl SignatureSet {
/// * capacity: The number of items to allocate memory for. /// * capacity: The number of items to allocate memory for.
pub fn with_capacity(capacity: usize) -> Self { pub fn with_capacity(capacity: usize) -> Self {
Self { Self {
set: HashSet::with_capacity(capacity), map: HashMap::with_capacity(capacity),
} }
} }
/// Adds a signature to the set. /// Adds a signature to the set.
/// ///
/// The boolean return value indicates whether or not the value was actually inserted, since /// If no signature with the given key ID existed in the collection, `None` is returned.
/// subsequent inserts of the same signature have no effect. /// Otherwise, the signature is returned.
/// ///
/// # Parameters /// # Parameters
/// ///
/// * signature: A `Signature` to insert into the set. /// * signature: A `Signature` to insert into the set.
pub fn insert(&mut self, signature: Signature) -> bool { pub fn insert(&mut self, signature: Signature) -> Option<Signature> {
self.set.insert(signature) self.map.insert(signature.id(), signature)
}
/// Gets a reference to the signature with the given key ID, if any.
///
/// # Parameters
///
/// * key_id: The identifier of the public key (e.g. "ed25519:1") for the desired signature.
pub fn get(&self, key_id: &str) -> Option<&Signature> {
self.map.get(key_id)
}
/// Gets a mutable reference to the signature with the given ID, if any.
///
/// # Parameters
///
/// * key_id: The identifier of the public key (e.g. "ed25519:1") for the desired signature.
pub fn get_mut(&mut self, key_id: &str) -> Option<&mut Signature> {
self.map.get_mut(key_id)
} }
/// The number of signatures in the set. /// The number of signatures in the set.
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.set.len() self.map.len()
} }
/// Whether or not the set of signatures is empty. /// Whether or not the set of signatures is empty.
@ -308,7 +326,7 @@ impl Serialize for SignatureSet {
{ {
let mut map_serializer = serializer.serialize_map(Some(self.len()))?; let mut map_serializer = serializer.serialize_map(Some(self.len()))?;
for signature in self.set.iter() { for signature in self.map.values() {
map_serializer.serialize_key(&signature.id())?; map_serializer.serialize_key(&signature.id())?;
map_serializer.serialize_value(&signature.base64())?; map_serializer.serialize_value(&signature.base64())?;
} }