summaryrefslogtreecommitdiffstats
path: root/openpgp/src/cert/bundle.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp/src/cert/bundle.rs')
-rw-r--r--openpgp/src/cert/bundle.rs143
1 files changed, 142 insertions, 1 deletions
diff --git a/openpgp/src/cert/bundle.rs b/openpgp/src/cert/bundle.rs
index eaaca0ef..077dfdc0 100644
--- a/openpgp/src/cert/bundle.rs
+++ b/openpgp/src/cert/bundle.rs
@@ -79,7 +79,8 @@
//! [complicated semantics]: https://tools.ietf.org/html/rfc4880#section-5.2.3.3
use std::time;
-use std::ops::Deref;
+use std::cmp::{self, Ordering};
+use std::ops::{Deref, DerefMut};
use crate::{
Error,
@@ -1057,3 +1058,143 @@ impl ComponentBundle<Unknown> {
self.component()
}
}
+
+/// A collection of `ComponentBundles`.
+///
+/// Note: we need this, because we can't `impl Vec<ComponentBundles>`.
+#[derive(Debug, Clone, PartialEq)]
+pub(super) struct ComponentBundles<C>
+ where ComponentBundle<C>: cmp::PartialEq
+{
+ bundles: Vec<ComponentBundle<C>>,
+}
+
+impl<C> Default for ComponentBundles<C>
+where
+ ComponentBundle<C>: cmp::PartialEq,
+{
+ fn default() -> Self {
+ ComponentBundles {
+ bundles: vec![],
+ }
+ }
+}
+
+impl<C> Deref for ComponentBundles<C>
+ where ComponentBundle<C>: cmp::PartialEq
+{
+ type Target = Vec<ComponentBundle<C>>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.bundles
+ }
+}
+
+impl<C> DerefMut for ComponentBundles<C>
+ where ComponentBundle<C>: cmp::PartialEq
+{
+ fn deref_mut(&mut self) -> &mut Vec<ComponentBundle<C>> {
+ &mut self.bundles
+ }
+}
+
+impl<C> From<ComponentBundles<C>> for Vec<ComponentBundle<C>>
+ where ComponentBundle<C>: cmp::PartialEq
+{
+ fn from(cb: ComponentBundles<C>) -> Vec<ComponentBundle<C>> {
+ cb.bundles
+ }
+}
+
+impl<C> From<Vec<ComponentBundle<C>>> for ComponentBundles<C>
+ where ComponentBundle<C>: cmp::PartialEq
+{
+ fn from(bundles: Vec<ComponentBundle<C>>) -> ComponentBundles<C> {
+ ComponentBundles {
+ bundles,
+ }
+ }
+}
+
+impl<C> IntoIterator for ComponentBundles<C>
+ where ComponentBundle<C>: cmp::PartialEq
+{
+ type Item = ComponentBundle<C>;
+ type IntoIter = std::vec::IntoIter<Self::Item>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.bundles.into_iter()
+ }
+}
+
+impl<C> ComponentBundles<C>
+ where ComponentBundle<C>: cmp::PartialEq
+{
+ // Sort and dedup the components.
+ //
+ // `cmp` is a function to sort the components for deduping.
+ //
+ // `merge` is a function that merges the first component into the
+ // second component.
+ pub(super) fn sort_and_dedup<F, F2>(&mut self, cmp: F, merge: F2)
+ where F: Fn(&C, &C) -> Ordering,
+ F2: Fn(&mut C, &mut C)
+ {
+ // We dedup by component (not bundles!). To do this, we need
+ // to sort the bundles by their components.
+
+ self.bundles.sort_by(
+ |a, b| cmp(&a.component, &b.component));
+
+ self.bundles.dedup_by(|a, b| {
+ if cmp(&a.component, &b.component) == Ordering::Equal {
+ // Merge.
+ merge(&mut a.component, &mut b.component);
+
+ // Recall: if a and b are equal, a will be dropped.
+ // Also, the elements are given in the opposite order
+ // from their order in the vector.
+ b.self_signatures.append(&mut a.self_signatures);
+ b.attestations.append(&mut a.attestations);
+ b.certifications.append(&mut a.certifications);
+ b.self_revocations.append(&mut a.self_revocations);
+ b.other_revocations.append(&mut a.other_revocations);
+
+ true
+ } else {
+ false
+ }
+ });
+
+ // And sort the certificates.
+ for b in self.bundles.iter_mut() {
+ b.sort_and_dedup();
+ }
+ }
+}
+
+/// A vecor of key (primary or subkey, public or private) and any
+/// associated signatures.
+pub(super) type KeyBundles<KeyPart, KeyRole>
+ = ComponentBundles<Key<KeyPart, KeyRole>>;
+
+/// A vector of subkeys and any associated signatures.
+pub(super) type SubkeyBundles<KeyPart>
+ = KeyBundles<KeyPart, key::SubordinateRole>;
+
+/// A vector of key (primary or subkey, public or private) and any
+/// associated signatures.
+#[allow(dead_code)]
+pub(super) type GenericKeyBundles
+ = ComponentBundles<Key<key::UnspecifiedParts, key::UnspecifiedRole>>;
+
+/// A vector of User ID bundles and any associated signatures.
+pub(super) type UserIDBundles = ComponentBundles<UserID>;
+
+/// A vector of User Attribute bundles and any associated signatures.
+pub(super) type UserAttributeBundles = ComponentBundles<UserAttribute>;
+
+/// A vector of unknown components and any associated signatures.
+///
+/// Note: all signatures are stored as certifications.
+pub(super) type UnknownBundles = ComponentBundles<Unknown>;