summaryrefslogtreecommitdiffstats
path: root/openpgp/src/packet
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2020-09-29 11:54:26 +0200
committerJustus Winter <justus@sequoia-pgp.org>2020-09-29 12:02:52 +0200
commit5beeeeb1989155489687c3a13f6592581ae8d7ce (patch)
treefbfe67f713059b6a94f94354602e398ee48f9774 /openpgp/src/packet
parentc84afa6db3f9605d9c763b07484c78fab7bc659f (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/src/packet')
-rw-r--r--openpgp/src/packet/mod.rs2
-rw-r--r--openpgp/src/packet/signature/mod.rs21
-rw-r--r--openpgp/src/packet/signature/subpacket.rs78
3 files changed, 71 insertions, 30 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,