From 2c3f8c86434692224a5f690b34e9aace37e09d1f Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Wed, 17 Apr 2024 15:43:17 +0200 Subject: openpgp: Move ComponentBundles to cert::bundles. --- openpgp/src/cert.rs | 136 ++------------------ openpgp/src/cert/bundle.rs | 143 +++++++++++++++++++++- openpgp/src/cert/parser/low_level/grammar.lalrpop | 8 +- 3 files changed, 154 insertions(+), 133 deletions(-) diff --git a/openpgp/src/cert.rs b/openpgp/src/cert.rs index 67a98526..d187d42f 100644 --- a/openpgp/src/cert.rs +++ b/openpgp/src/cert.rs @@ -131,14 +131,12 @@ use std::io; use std::collections::btree_map::BTreeMap; use std::collections::btree_map::Entry; use std::collections::hash_map::DefaultHasher; -use std::cmp; use std::cmp::Ordering; use std::convert::TryFrom; use std::hash::Hasher; use std::path::Path; use std::mem; use std::fmt; -use std::ops::{Deref, DerefMut}; use std::time; use buffered_reader::BufferedReader; @@ -184,6 +182,13 @@ pub mod amalgamation; mod builder; mod bindings; pub mod bundle; +use bundle::{ + ComponentBundles, + UserIDBundles, + UserAttributeBundles, + SubkeyBundles, + UnknownBundles, +}; mod parser; pub mod raw; mod revoke; @@ -247,131 +252,6 @@ impl fmt::Display for Cert { } } -/// A collection of `ComponentBundles`. -/// -/// Note: we need this, because we can't `impl Vec`. -#[derive(Debug, Clone, PartialEq)] -struct ComponentBundles - where ComponentBundle: cmp::PartialEq -{ - bundles: Vec>, -} - -impl Deref for ComponentBundles - where ComponentBundle: cmp::PartialEq -{ - type Target = Vec>; - - fn deref(&self) -> &Self::Target { - &self.bundles - } -} - -impl DerefMut for ComponentBundles - where ComponentBundle: cmp::PartialEq -{ - fn deref_mut(&mut self) -> &mut Vec> { - &mut self.bundles - } -} - -impl From> for Vec> - where ComponentBundle: cmp::PartialEq -{ - fn from(cb: ComponentBundles) -> Vec> { - cb.bundles - } -} - -impl IntoIterator for ComponentBundles - where ComponentBundle: cmp::PartialEq -{ - type Item = ComponentBundle; - type IntoIter = std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.bundles.into_iter() - } -} - -impl ComponentBundles - where ComponentBundle: cmp::PartialEq -{ - fn new() -> Self { - Self { bundles: vec![] } - } -} - -impl ComponentBundles - where ComponentBundle: 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. - fn sort_and_dedup(&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. -type KeyBundles = ComponentBundles>; - -/// A vector of subkeys and any associated signatures. -type SubkeyBundles = KeyBundles; - -/// A vector of key (primary or subkey, public or private) and any -/// associated signatures. -#[allow(dead_code)] -type GenericKeyBundles - = ComponentBundles>; - -/// A vector of User ID bundles and any associated signatures. -type UserIDBundles = ComponentBundles; - -/// A vector of User Attribute bundles and any associated signatures. -type UserAttributeBundles = ComponentBundles; - -/// A vector of unknown components and any associated signatures. -/// -/// Note: all signatures are stored as certifications. -type UnknownBundles = ComponentBundles; - /// Returns the certificate holder's preferences. /// /// OpenPGP provides a mechanism for a certificate holder to transmit @@ -3310,7 +3190,7 @@ impl Cert { kb }) .collect::>(); - self.subkeys = ComponentBundles { bundles: subkeys, }; + self.subkeys = subkeys.into(); self } 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 { self.component() } } + +/// A collection of `ComponentBundles`. +/// +/// Note: we need this, because we can't `impl Vec`. +#[derive(Debug, Clone, PartialEq)] +pub(super) struct ComponentBundles + where ComponentBundle: cmp::PartialEq +{ + bundles: Vec>, +} + +impl Default for ComponentBundles +where + ComponentBundle: cmp::PartialEq, +{ + fn default() -> Self { + ComponentBundles { + bundles: vec![], + } + } +} + +impl Deref for ComponentBundles + where ComponentBundle: cmp::PartialEq +{ + type Target = Vec>; + + fn deref(&self) -> &Self::Target { + &self.bundles + } +} + +impl DerefMut for ComponentBundles + where ComponentBundle: cmp::PartialEq +{ + fn deref_mut(&mut self) -> &mut Vec> { + &mut self.bundles + } +} + +impl From> for Vec> + where ComponentBundle: cmp::PartialEq +{ + fn from(cb: ComponentBundles) -> Vec> { + cb.bundles + } +} + +impl From>> for ComponentBundles + where ComponentBundle: cmp::PartialEq +{ + fn from(bundles: Vec>) -> ComponentBundles { + ComponentBundles { + bundles, + } + } +} + +impl IntoIterator for ComponentBundles + where ComponentBundle: cmp::PartialEq +{ + type Item = ComponentBundle; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.bundles.into_iter() + } +} + +impl ComponentBundles + where ComponentBundle: 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(&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 + = ComponentBundles>; + +/// A vector of subkeys and any associated signatures. +pub(super) type SubkeyBundles + = KeyBundles; + +/// A vector of key (primary or subkey, public or private) and any +/// associated signatures. +#[allow(dead_code)] +pub(super) type GenericKeyBundles + = ComponentBundles>; + +/// A vector of User ID bundles and any associated signatures. +pub(super) type UserIDBundles = ComponentBundles; + +/// A vector of User Attribute bundles and any associated signatures. +pub(super) type UserAttributeBundles = ComponentBundles; + +/// A vector of unknown components and any associated signatures. +/// +/// Note: all signatures are stored as certifications. +pub(super) type UnknownBundles = ComponentBundles; diff --git a/openpgp/src/cert/parser/low_level/grammar.lalrpop b/openpgp/src/cert/parser/low_level/grammar.lalrpop index d1b41be5..f1bf420e 100644 --- a/openpgp/src/cert/parser/low_level/grammar.lalrpop +++ b/openpgp/src/cert/parser/low_level/grammar.lalrpop @@ -61,10 +61,10 @@ pub Cert: Option = { self_revocations: vec![], other_revocations: vec![], }, - subkeys: ComponentBundles::new(), - userids: ComponentBundles::new(), - user_attributes: ComponentBundles::new(), - unknowns: ComponentBundles::new(), + subkeys: ComponentBundles::default(), + userids: ComponentBundles::default(), + user_attributes: ComponentBundles::default(), + unknowns: ComponentBundles::default(), bad: vec![], }; -- cgit v1.2.3