diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2020-09-29 11:54:26 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2020-09-29 12:02:52 +0200 |
commit | 5beeeeb1989155489687c3a13f6592581ae8d7ce (patch) | |
tree | fbfe67f713059b6a94f94354602e398ee48f9774 /openpgp | |
parent | c84afa6db3f9605d9c763b07484c78fab7bc659f (diff) |
openpgp: Implement PartialOrd, Ord for signature-related types.
- In order to deduplicate signatures, we need to be able to sort
them. This change implements PartialOrd and Ord for all relevant
types. Like PartialEq and Eq it is based on the serialized form,
and can be derived for most of the types.
Diffstat (limited to 'openpgp')
-rw-r--r-- | openpgp/src/packet/mod.rs | 2 | ||||
-rw-r--r-- | openpgp/src/packet/signature/mod.rs | 21 | ||||
-rw-r--r-- | openpgp/src/packet/signature/subpacket.rs | 78 | ||||
-rw-r--r-- | openpgp/src/types/bitfield.rs | 2 | ||||
-rw-r--r-- | openpgp/src/types/features.rs | 2 | ||||
-rw-r--r-- | openpgp/src/types/key_flags.rs | 2 | ||||
-rw-r--r-- | openpgp/src/types/mod.rs | 2 | ||||
-rw-r--r-- | openpgp/src/types/revocation_key.rs | 2 | ||||
-rw-r--r-- | openpgp/src/types/server_preferences.rs | 2 |
9 files changed, 77 insertions, 36 deletions
diff --git a/openpgp/src/packet/mod.rs b/openpgp/src/packet/mod.rs index f18a9d6d..a078e9a4 100644 --- a/openpgp/src/packet/mod.rs +++ b/openpgp/src/packet/mod.rs @@ -876,7 +876,7 @@ fn packet_path_iter() { /// # assert_eq!(cert.with_policy(p, t2)?.userids().count(), 2); /// # Ok(()) } /// ``` -#[derive(PartialEq, Eq, Hash, Clone, Debug)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Debug)] pub enum Signature { /// Signature packet version 4. V4(self::signature::Signature4), diff --git a/openpgp/src/packet/signature/mod.rs b/openpgp/src/packet/signature/mod.rs index f7eec3f8..edbab5f2 100644 --- a/openpgp/src/packet/signature/mod.rs +++ b/openpgp/src/packet/signature/mod.rs @@ -114,6 +114,7 @@ //! [`SubpacketAreas`]: subpacket/struct.SubpacketAreas.html //! [its documentation]: subpacket/struct.SubpacketAreas.html +use std::cmp::Ordering; use std::fmt; use std::ops::{Deref, DerefMut}; use std::time::SystemTime; @@ -206,7 +207,7 @@ pub(crate) const SIG_BACKDATE_BY: u64 = 60; /// [`Signature4`]: struct.Signature4.html /// [`SignatureBuilder`]: struct.SignatureBuilder.html /// [`SubpacketAreas`]: subpacket/struct.SubpacketAreas.html -#[derive(Clone, Hash, PartialEq, Eq)] +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct SignatureFields { /// Version of the signature packet. Must be 4. version: u8, @@ -1684,14 +1685,26 @@ impl PartialEq for Signature4 { /// [`computed_digest`]: #method.computed_digest /// [`Signature4::normalized_eq`]: #method.normalized_eq fn eq(&self, other: &Signature4) -> bool { - self.mpis == other.mpis - && self.fields == other.fields - && self.digest_prefix == other.digest_prefix + self.cmp(other) == Ordering::Equal } } impl Eq for Signature4 {} +impl PartialOrd for Signature4 { + fn partial_cmp(&self, other: &Signature4) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl Ord for Signature4 { + fn cmp(&self, other: &Signature4) -> Ordering { + self.mpis.cmp(&other.mpis) + .then_with(|| self.fields.cmp(&other.fields)) + .then_with(|| self.digest_prefix.cmp(&other.digest_prefix)) + } +} + impl std::hash::Hash for Signature4 { fn hash<H: std::hash::Hasher>(&self, state: &mut H) { use std::hash::Hash as StdHash; diff --git a/openpgp/src/packet/signature/subpacket.rs b/openpgp/src/packet/signature/subpacket.rs index 62494df9..b6bb5f81 100644 --- a/openpgp/src/packet/signature/subpacket.rs +++ b/openpgp/src/packet/signature/subpacket.rs @@ -54,6 +54,7 @@ //! ``` use std::cell::RefCell; +use std::cmp::Ordering; use std::collections::HashMap; use std::convert::{TryInto, TryFrom}; use std::hash::{Hash, Hasher}; @@ -535,11 +536,24 @@ impl Clone for SubpacketArea { impl PartialEq for SubpacketArea { fn eq(&self, other: &SubpacketArea) -> bool { - self.packets == other.packets + self.cmp(other) == Ordering::Equal } } + impl Eq for SubpacketArea {} +impl PartialOrd for SubpacketArea { + fn partial_cmp(&self, other: &SubpacketArea) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl Ord for SubpacketArea { + fn cmp(&self, other: &SubpacketArea) -> Ordering { + self.packets.cmp(&other.packets) + } +} + impl Hash for SubpacketArea { fn hash<H: Hasher>(&self, state: &mut H) { // We hash only the data, the cache is a hashmap and does not @@ -969,7 +983,7 @@ impl SubpacketArea { /// 5.2.3.16 of RFC 4880] for details. /// /// [Section 5.2.3.16 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.16 -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct NotationData { flags: NotationDataFlags, name: String, @@ -1018,7 +1032,7 @@ impl NotationData { } /// Flags for the Notation Data subpacket. -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct NotationDataFlags(crate::types::Bitfield); #[cfg(test)] @@ -1194,7 +1208,7 @@ impl NotationDataFlags { /// /// Note: This enum cannot be exhaustively matched to allow future /// extensions. -#[derive(Debug, PartialEq, Eq, Hash, Clone)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)] pub enum SubpacketValue { /// An unknown subpacket. Unknown { @@ -1559,7 +1573,7 @@ impl SubpacketValue { /// Subpackets are described in [Section 5.2.3.1 of RFC 4880]. /// /// [Section 5.2.3.1 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.1 -#[derive(PartialEq, Eq, Hash, Clone)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone)] pub struct Subpacket { /// The length. /// @@ -1693,25 +1707,7 @@ impl From<u32> for SubpacketLength { impl PartialEq for SubpacketLength { fn eq(&self, other: &Self) -> bool { - match (&self.raw, &other.raw) { - (None, None) => { - self.len == other.len - }, - // Compare serialized representations if at least one is given - (Some(self_raw), Some(other_raw)) => { - self_raw == other_raw - }, - (Some(self_raw), None) => { - let mut other_raw = [0; 5]; - other.serialize_into(&mut other_raw[..self.serialized_len()]).unwrap(); - &self_raw[..] == &other_raw[..self.serialized_len()] - }, - (None, Some(other_raw)) => { - let mut self_raw = [0; 5]; - self.serialize_into(&mut self_raw[..self.serialized_len()]).unwrap(); - &self_raw[..self.serialized_len()] == &other_raw[..] - }, - } + self.cmp(other) == Ordering::Equal } } @@ -1731,6 +1727,38 @@ impl Hash for SubpacketLength { } } +impl PartialOrd for SubpacketLength { + fn partial_cmp(&self, other: &SubpacketLength) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl Ord for SubpacketLength { + fn cmp(&self, other: &SubpacketLength) -> Ordering { + match (&self.raw, &other.raw) { + (None, None) => { + self.len.cmp(&other.len) + }, + // Compare serialized representations if at least one is given + (Some(self_raw), Some(other_raw)) => { + self_raw.cmp(other_raw) + }, + (Some(self_raw), None) => { + let mut other_raw = [0; 5]; + other.serialize_into(&mut other_raw[..self.serialized_len()]) + .unwrap(); + self_raw[..].cmp(&other_raw[..self.serialized_len()]) + }, + (None, Some(other_raw)) => { + let mut self_raw = [0; 5]; + self.serialize_into(&mut self_raw[..self.serialized_len()]) + .unwrap(); + self_raw[..self.serialized_len()].cmp(&other_raw[..]) + }, + } + } +} + impl SubpacketLength { pub(crate) fn new(len: u32, raw: Option<Vec<u8>>) -> Self { Self { len, raw } @@ -1764,7 +1792,7 @@ impl SubpacketLength { /// hash area are preferred. To return packets from a specific area, /// use the `hashed_area` and `unhashed_area` methods to get the /// specific methods and then use their accessors. -#[derive(Clone, Default, PartialEq, Eq, Hash)] +#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct SubpacketAreas { /// Subpackets that are part of the signature. hashed_area: SubpacketArea, diff --git a/openpgp/src/types/bitfield.rs b/openpgp/src/types/bitfield.rs index 0b45d3ad..d4a896bc 100644 --- a/openpgp/src/types/bitfield.rs +++ b/openpgp/src/types/bitfield.rs @@ -1,5 +1,5 @@ /// A bitfield. -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub(crate) struct Bitfield { pub(crate) raw: Vec<u8>, } diff --git a/openpgp/src/types/features.rs b/openpgp/src/types/features.rs index 828d76fb..948a5cb0 100644 --- a/openpgp/src/types/features.rs +++ b/openpgp/src/types/features.rs @@ -53,7 +53,7 @@ use crate::types::Bitfield; /// } /// # Ok(()) } /// ``` -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Features(Bitfield); impl fmt::Debug for Features { diff --git a/openpgp/src/types/key_flags.rs b/openpgp/src/types/key_flags.rs index f100768f..3909dbfe 100644 --- a/openpgp/src/types/key_flags.rs +++ b/openpgp/src/types/key_flags.rs @@ -47,7 +47,7 @@ use crate::types::Bitfield; /// } /// # Ok(()) } /// ``` -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct KeyFlags(Bitfield); impl fmt::Debug for KeyFlags { diff --git a/openpgp/src/types/mod.rs b/openpgp/src/types/mod.rs index cf3b4568..928b0d20 100644 --- a/openpgp/src/types/mod.rs +++ b/openpgp/src/types/mod.rs @@ -1112,7 +1112,7 @@ impl Arbitrary for HashAlgorithm { /// .set_signature_creation_time(SystemTime::now())?; /// # Ok(()) } /// ``` -#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)] pub enum SignatureType { /// Signature over a binary document. Binary, diff --git a/openpgp/src/types/revocation_key.rs b/openpgp/src/types/revocation_key.rs index e2b36042..f4dc7c49 100644 --- a/openpgp/src/types/revocation_key.rs +++ b/openpgp/src/types/revocation_key.rs @@ -52,7 +52,7 @@ use crate::{ /// vec![&(&alice).into()]); /// # Ok(()) } /// ``` -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct RevocationKey { /// The public key algorithm used by the authorized key. pk_algo: PublicKeyAlgorithm, diff --git a/openpgp/src/types/server_preferences.rs b/openpgp/src/types/server_preferences.rs index ec58d9b2..fdac56fc 100644 --- a/openpgp/src/types/server_preferences.rs +++ b/openpgp/src/types/server_preferences.rs @@ -54,7 +54,7 @@ use crate::types::Bitfield; /// } /// # Ok(()) } /// ``` -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct KeyServerPreferences(Bitfield); impl fmt::Debug for KeyServerPreferences { |