From 4bf075658d00d1a7ddb2a3b309a40a4d2b24608c Mon Sep 17 00:00:00 2001 From: roblabla Date: Thu, 15 Sep 2022 12:32:46 +0200 Subject: [PATCH 1/5] Implement ValueOrd for FlagSet --- der/src/asn1/bit_string.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/der/src/asn1/bit_string.rs b/der/src/asn1/bit_string.rs index 7eea5a596..eed14e456 100644 --- a/der/src/asn1/bit_string.rs +++ b/der/src/asn1/bit_string.rs @@ -375,6 +375,17 @@ impl FixedTag for flagset::FlagSet { const TAG: Tag = BitStringRef::TAG; } +#[cfg(feature = "flagset")] +impl ValueOrd for flagset::FlagSet +where + T: flagset::Flags, + T::Type: Ord, +{ + fn value_cmp(&self, other: &Self) -> Result { + Ok(self.bits().cmp(&other.bits())) + } +} + #[cfg(feature = "flagset")] #[allow(clippy::integer_arithmetic)] impl<'a, T> DecodeValue<'a> for flagset::FlagSet From 20f40ab8b71ae08d89528bf051b29d414b8a6f50 Mon Sep 17 00:00:00 2001 From: roblabla Date: Thu, 15 Sep 2022 12:37:46 +0200 Subject: [PATCH 2/5] Implement ValueOrd for UIntRef --- der/src/asn1/integer/bigint.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/der/src/asn1/integer/bigint.rs b/der/src/asn1/integer/bigint.rs index 7a73c480a..f896406a6 100644 --- a/der/src/asn1/integer/bigint.rs +++ b/der/src/asn1/integer/bigint.rs @@ -2,8 +2,8 @@ use super::uint; use crate::{ - asn1::AnyRef, ByteSlice, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, - Reader, Result, Tag, Writer, + asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, ErrorKind, + FixedTag, Header, Length, Reader, Result, Tag, Writer, }; /// "Big" unsigned ASN.1 `INTEGER` type. @@ -13,7 +13,7 @@ use crate::{ /// /// Intended for use cases like very large integers that are used in /// cryptographic applications (e.g. keys, signatures). -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct UIntRef<'a> { /// Inner value inner: ByteSlice<'a>, @@ -92,6 +92,8 @@ impl<'a> FixedTag for UIntRef<'a> { const TAG: Tag = Tag::Integer; } +impl<'a> OrdIsValueOrd for UIntRef<'a> {} + #[cfg(test)] mod tests { use super::UIntRef; From 67d606d5b4e6b858544638b8f65df721e109568b Mon Sep 17 00:00:00 2001 From: roblabla Date: Fri, 16 Sep 2022 11:55:58 +0200 Subject: [PATCH 3/5] Implement ValueOrd for x509-cert Version --- x509-cert/src/certificate.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/x509-cert/src/certificate.rs b/x509-cert/src/certificate.rs index cca7f8391..b9932cdd3 100644 --- a/x509-cert/src/certificate.rs +++ b/x509-cert/src/certificate.rs @@ -3,10 +3,11 @@ use crate::{name::Name, time::Validity}; use alloc::vec::Vec; +use core::cmp::Ordering; use const_oid::AssociatedOid; use der::asn1::{BitStringRef, UIntRef}; -use der::{Decode, Enumerated, Error, ErrorKind, Sequence}; +use der::{Decode, Enumerated, Error, ErrorKind, Sequence, ValueOrd}; use spki::{AlgorithmIdentifier, SubjectPublicKeyInfo}; /// Certificate `Version` as defined in [RFC 5280 Section 4.1]. @@ -30,6 +31,12 @@ pub enum Version { V3 = 2, } +impl ValueOrd for Version { + fn value_cmp(&self, other: &Self) -> der::Result { + (&(*self as u8)).value_cmp(&(*other as u8)) + } +} + impl Default for Version { fn default() -> Self { Self::V1 @@ -61,7 +68,7 @@ impl Default for Version { /// ``` /// /// [RFC 5280 Section 4.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1 -#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] pub struct TbsCertificate<'a> { /// The certificate version @@ -135,7 +142,7 @@ impl<'a> TbsCertificate<'a> { /// ``` /// /// [RFC 5280 Section 4.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1 -#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] pub struct Certificate<'a> { pub tbs_certificate: TbsCertificate<'a>, From 97262304b86e80be2cd131a063b82777e85691f0 Mon Sep 17 00:00:00 2001 From: roblabla Date: Fri, 16 Sep 2022 11:57:59 +0200 Subject: [PATCH 4/5] Allow deriving ValueOrd on Choice enums --- der/derive/src/value_ord.rs | 107 +++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 33 deletions(-) diff --git a/der/derive/src/value_ord.rs b/der/derive/src/value_ord.rs index 6b08f7ffd..f385058f5 100644 --- a/der/derive/src/value_ord.rs +++ b/der/derive/src/value_ord.rs @@ -21,6 +21,8 @@ pub(crate) struct DeriveValueOrd { /// Fields of structs or enum variants. fields: Vec, + + is_enum: bool, } impl DeriveValueOrd { @@ -36,17 +38,21 @@ impl DeriveValueOrd { .next() .map(|lt| lt.lifetime.clone()); - let fields = match input.data { - syn::Data::Enum(data) => data - .variants - .into_iter() - .map(|variant| ValueField::new_enum(variant, &type_attrs)) - .collect(), - syn::Data::Struct(data) => data - .fields - .into_iter() - .map(|field| ValueField::new_struct(field, &type_attrs)) - .collect(), + let (fields, is_enum) = match input.data { + syn::Data::Enum(data) => ( + data.variants + .into_iter() + .map(|variant| ValueField::new_enum(variant, &type_attrs)) + .collect(), + true, + ), + syn::Data::Struct(data) => ( + data.fields + .into_iter() + .map(|field| ValueField::new_struct(field, &type_attrs)) + .collect(), + false, + ), _ => abort!( ident, "can't derive `ValueOrd` on this type: \ @@ -58,6 +64,7 @@ impl DeriveValueOrd { ident, lifetime, fields, + is_enum, } } @@ -79,15 +86,30 @@ impl DeriveValueOrd { body.push(field.to_tokens()); } + let body = if self.is_enum { + quote! { + #[allow(unused_imports)] + use ::der::ValueOrd; + match (self, other) { + #(#body)* + _ => unreachable!(), + } + } + } else { + quote! { + #[allow(unused_imports)] + use ::der::{DerOrd, ValueOrd}; + + #(#body)* + + Ok(::core::cmp::Ordering::Equal) + } + }; + quote! { impl<#(#lt_params)*> ::der::ValueOrd for #ident<#(#lt_params)*> { fn value_cmp(&self, other: &Self) -> ::der::Result<::core::cmp::Ordering> { - #[allow(unused_imports)] - use ::der::DerOrd; - - #(#body)* - - Ok(::core::cmp::Ordering::Equal) + #body } } } @@ -100,15 +122,21 @@ struct ValueField { /// Field-level attributes. attrs: FieldAttrs, + + is_enum: bool, } impl ValueField { /// Create from an `enum` variant. - fn new_enum(variant: Variant, _: &TypeAttrs) -> Self { - abort!( - variant, - "deriving `ValueOrd` only presently supported for structs" - ); + fn new_enum(variant: Variant, type_attrs: &TypeAttrs) -> Self { + let ident = variant.ident; + + let attrs = FieldAttrs::parse(&variant.attrs, type_attrs); + Self { + ident, + attrs, + is_enum: true, + } } /// Create from a `struct` field. @@ -120,24 +148,37 @@ impl ValueField { .unwrap_or_else(|| abort!(&field, "tuple structs are not supported")); let attrs = FieldAttrs::parse(&field.attrs, type_attrs); - Self { ident, attrs } + Self { + ident, + attrs, + is_enum: false, + } } /// Lower to [`TokenStream`]. fn to_tokens(&self) -> TokenStream { let ident = &self.ident; - let mut binding1 = quote!(self.#ident); - let mut binding2 = quote!(other.#ident); - if let Some(ty) = &self.attrs.asn1_type { - binding1 = ty.encoder(&binding1); - binding2 = ty.encoder(&binding2); - } + if self.is_enum { + let binding1 = quote!(Self::#ident(this)); + let binding2 = quote!(Self::#ident(other)); + quote! { + (#binding1, #binding2) => this.value_cmp(other), + } + } else { + let mut binding1 = quote!(self.#ident); + let mut binding2 = quote!(other.#ident); - quote! { - match #binding1.der_cmp(&#binding2)? { - ::core::cmp::Ordering::Equal => (), - other => return Ok(other), + if let Some(ty) = &self.attrs.asn1_type { + binding1 = ty.encoder(&binding1); + binding2 = ty.encoder(&binding2); + } + + quote! { + match #binding1.der_cmp(&#binding2)? { + ::core::cmp::Ordering::Equal => (), + other => return Ok(other), + } } } } From 3b01ae85d0d2f99c7bf744097ae54fc4b31d8aab Mon Sep 17 00:00:00 2001 From: roblabla Date: Fri, 16 Sep 2022 11:58:35 +0200 Subject: [PATCH 5/5] Derive ValueOrd for a bunch of structs --- x509-cert/src/crl.rs | 8 ++++---- x509-cert/src/ext.rs | 4 ++-- x509-cert/src/ext/pkix/access.rs | 4 ++-- x509-cert/src/ext/pkix/certpolicy.rs | 6 +++--- x509-cert/src/ext/pkix/crl/dp.rs | 4 ++-- x509-cert/src/ext/pkix/name/dirstr.rs | 4 ++-- x509-cert/src/ext/pkix/name/dp.rs | 4 ++-- x509-cert/src/ext/pkix/name/ediparty.rs | 4 ++-- x509-cert/src/ext/pkix/name/general.rs | 4 ++-- x509-cert/src/ext/pkix/name/other.rs | 4 ++-- x509-cert/src/ext/pkix/policymap.rs | 4 ++-- x509-cert/src/macros.rs | 7 +++++++ x509-cert/src/time.rs | 6 +++--- 13 files changed, 35 insertions(+), 28 deletions(-) diff --git a/x509-cert/src/crl.rs b/x509-cert/src/crl.rs index 3e630435b..55fba27af 100644 --- a/x509-cert/src/crl.rs +++ b/x509-cert/src/crl.rs @@ -8,7 +8,7 @@ use crate::Version; use alloc::vec::Vec; use der::asn1::{BitStringRef, UIntRef}; -use der::Sequence; +use der::{Sequence, ValueOrd}; use spki::AlgorithmIdentifier; /// `CertificateList` as defined in [RFC 5280 Section 5.1]. @@ -22,7 +22,7 @@ use spki::AlgorithmIdentifier; /// ``` /// /// [RFC 5280 Section 5.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-5.1 -#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] pub struct CertificateList<'a> { pub tbs_cert_list: TbsCertList<'a>, @@ -44,7 +44,7 @@ pub struct CertificateList<'a> { /// ``` /// /// [RFC 5280 Section 5.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-5.1 -#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] pub struct RevokedCert<'a> { pub serial_number: UIntRef<'a>, @@ -71,7 +71,7 @@ pub struct RevokedCert<'a> { /// ``` /// /// [RFC 5280 Section 5.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-5.1 -#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] pub struct TbsCertList<'a> { pub version: Version, diff --git a/x509-cert/src/ext.rs b/x509-cert/src/ext.rs index d717a7c8a..eb6f6fbb8 100644 --- a/x509-cert/src/ext.rs +++ b/x509-cert/src/ext.rs @@ -1,6 +1,6 @@ //! Standardized X.509 Certificate Extensions -use der::Sequence; +use der::{Sequence, ValueOrd}; use spki::ObjectIdentifier; pub mod pkix; @@ -22,7 +22,7 @@ pub mod pkix; /// ``` /// /// [RFC 5280 Section 4.1.2.9]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.9 -#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] pub struct Extension<'a> { pub extn_id: ObjectIdentifier, diff --git a/x509-cert/src/ext/pkix/access.rs b/x509-cert/src/ext/pkix/access.rs index 5b74b6f86..0390235aa 100644 --- a/x509-cert/src/ext/pkix/access.rs +++ b/x509-cert/src/ext/pkix/access.rs @@ -6,7 +6,7 @@ use const_oid::{ db::rfc5280::{ID_PE_AUTHORITY_INFO_ACCESS, ID_PE_SUBJECT_INFO_ACCESS}, AssociatedOid, }; -use der::{asn1::ObjectIdentifier, Sequence}; +use der::{asn1::ObjectIdentifier, Sequence, ValueOrd}; /// AuthorityInfoAccessSyntax as defined in [RFC 5280 Section 4.2.2.1]. /// @@ -50,7 +50,7 @@ impl_newtype!(SubjectInfoAccessSyntax<'a>, Vec>); /// ``` /// /// [RFC 5280 Section 4.2.2.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.2.1 -#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] pub struct AccessDescription<'a> { pub access_method: ObjectIdentifier, diff --git a/x509-cert/src/ext/pkix/certpolicy.rs b/x509-cert/src/ext/pkix/certpolicy.rs index 382142741..bb2211fba 100644 --- a/x509-cert/src/ext/pkix/certpolicy.rs +++ b/x509-cert/src/ext/pkix/certpolicy.rs @@ -5,7 +5,7 @@ use alloc::vec::Vec; use const_oid::db::rfc5912::ID_CE_CERTIFICATE_POLICIES; use const_oid::AssociatedOid; use der::asn1::{GeneralizedTime, Ia5StringRef, ObjectIdentifier, UIntRef, Utf8StringRef}; -use der::{AnyRef, Choice, Sequence}; +use der::{AnyRef, Choice, Sequence, ValueOrd}; /// CertificatePolicies as defined in [RFC 5280 Section 4.2.1.4]. /// @@ -35,7 +35,7 @@ impl_newtype!(CertificatePolicies<'a>, Vec>); /// ``` /// /// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4 -#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] pub struct PolicyInformation<'a> { pub policy_identifier: ObjectIdentifier, @@ -52,7 +52,7 @@ pub struct PolicyInformation<'a> { /// ``` /// /// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4 -#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] pub struct PolicyQualifierInfo<'a> { pub policy_qualifier_id: ObjectIdentifier, diff --git a/x509-cert/src/ext/pkix/crl/dp.rs b/x509-cert/src/ext/pkix/crl/dp.rs index 7aa8a2d2d..f7d1ab724 100644 --- a/x509-cert/src/ext/pkix/crl/dp.rs +++ b/x509-cert/src/ext/pkix/crl/dp.rs @@ -1,7 +1,7 @@ //! PKIX distribution point types use const_oid::{db::rfc5280::ID_PE_SUBJECT_INFO_ACCESS, AssociatedOid, ObjectIdentifier}; -use der::Sequence; +use der::{Sequence, ValueOrd}; use flagset::{flags, FlagSet}; use crate::ext::pkix::name::{DistributionPointName, GeneralNames}; @@ -74,7 +74,7 @@ impl<'a> AssociatedOid for IssuingDistributionPoint<'a> { /// ``` /// /// [RFC 5280 Section 4.2.1.13]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.13 -#[derive(Clone, Debug, PartialEq, Eq, Sequence)] +#[derive(Clone, Debug, PartialEq, Eq, Sequence, ValueOrd)] #[allow(missing_docs)] pub struct DistributionPoint<'a> { #[asn1(context_specific = "0", tag_mode = "EXPLICIT", optional = "true")] diff --git a/x509-cert/src/ext/pkix/name/dirstr.rs b/x509-cert/src/ext/pkix/name/dirstr.rs index 283b53f11..2aaa732bd 100644 --- a/x509-cert/src/ext/pkix/name/dirstr.rs +++ b/x509-cert/src/ext/pkix/name/dirstr.rs @@ -1,5 +1,5 @@ use der::asn1::{PrintableStringRef, TeletexStringRef, Utf8StringRef}; -use der::Choice; +use der::{Choice, ValueOrd}; /// DirectoryString as defined in [RFC 5280 Section 4.2.1.4]. /// @@ -38,7 +38,7 @@ use der::Choice; /// the need arises, we only support `PrintableString` and `UTF8String`. /// /// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4 -#[derive(Clone, Debug, Eq, PartialEq, Choice)] +#[derive(Clone, Debug, Eq, PartialEq, Choice, ValueOrd)] #[allow(missing_docs)] pub enum DirectoryString<'a> { #[asn1(type = "PrintableString")] diff --git a/x509-cert/src/ext/pkix/name/dp.rs b/x509-cert/src/ext/pkix/name/dp.rs index 3cfdf969a..e895f88a0 100644 --- a/x509-cert/src/ext/pkix/name/dp.rs +++ b/x509-cert/src/ext/pkix/name/dp.rs @@ -1,7 +1,7 @@ use super::GeneralNames; use crate::name::RelativeDistinguishedName; -use der::Choice; +use der::{Choice, ValueOrd}; /// DistributionPointName as defined in [RFC 5280 Section 4.2.1.13]. /// @@ -13,7 +13,7 @@ use der::Choice; /// ``` /// /// [RFC 5280 Section 4.2.1.13]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.13 -#[derive(Clone, Debug, Eq, PartialEq, Choice)] +#[derive(Clone, Debug, Eq, PartialEq, Choice, ValueOrd)] #[allow(missing_docs)] pub enum DistributionPointName<'a> { #[asn1(context_specific = "0", tag_mode = "IMPLICIT", constructed = "true")] diff --git a/x509-cert/src/ext/pkix/name/ediparty.rs b/x509-cert/src/ext/pkix/name/ediparty.rs index 06ee320b3..94af09b00 100644 --- a/x509-cert/src/ext/pkix/name/ediparty.rs +++ b/x509-cert/src/ext/pkix/name/ediparty.rs @@ -1,4 +1,4 @@ -use der::Sequence; +use der::{Sequence, ValueOrd}; use super::DirectoryString; @@ -25,7 +25,7 @@ use super::DirectoryString; /// /// [this OpenSSL bug]: https://github.com/openssl/openssl/issues/6859 /// [RFC 5280 Section 4.2.1.6]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6 -#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] pub struct EdiPartyName<'a> { #[asn1(context_specific = "0", tag_mode = "EXPLICIT", optional = "true")] diff --git a/x509-cert/src/ext/pkix/name/general.rs b/x509-cert/src/ext/pkix/name/general.rs index 0daa36846..f6861d4c7 100644 --- a/x509-cert/src/ext/pkix/name/general.rs +++ b/x509-cert/src/ext/pkix/name/general.rs @@ -4,7 +4,7 @@ use super::{EdiPartyName, OtherName}; use crate::name::Name; use der::asn1::{Ia5StringRef, ObjectIdentifier, OctetStringRef}; -use der::Choice; +use der::{Choice, ValueOrd}; /// GeneralNames as defined in [RFC 5280 Section 4.2.1.6]. /// @@ -34,7 +34,7 @@ pub type GeneralNames<'a> = alloc::vec::Vec>; /// This implementation does not currently support the `x400Address` choice. /// /// [RFC 5280 Section 4.2.1.6]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6 -#[derive(Clone, Debug, Eq, PartialEq, Choice)] +#[derive(Clone, Debug, Eq, PartialEq, Choice, ValueOrd)] #[allow(missing_docs)] pub enum GeneralName<'a> { #[asn1(context_specific = "0", tag_mode = "IMPLICIT", constructed = "true")] diff --git a/x509-cert/src/ext/pkix/name/other.rs b/x509-cert/src/ext/pkix/name/other.rs index 4a250bb45..a33601c07 100644 --- a/x509-cert/src/ext/pkix/name/other.rs +++ b/x509-cert/src/ext/pkix/name/other.rs @@ -1,4 +1,4 @@ -use der::{asn1::ObjectIdentifier, AnyRef, Sequence}; +use der::{asn1::ObjectIdentifier, AnyRef, Sequence, ValueOrd}; /// OtherName as defined in [RFC 5280 Section 4.2.1.6]. /// @@ -10,7 +10,7 @@ use der::{asn1::ObjectIdentifier, AnyRef, Sequence}; /// ``` /// /// [RFC 5280 Section 4.2.1.6]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6 -#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] pub struct OtherName<'a> { pub type_id: ObjectIdentifier, diff --git a/x509-cert/src/ext/pkix/policymap.rs b/x509-cert/src/ext/pkix/policymap.rs index 35b1d4987..e6b55bad5 100644 --- a/x509-cert/src/ext/pkix/policymap.rs +++ b/x509-cert/src/ext/pkix/policymap.rs @@ -3,7 +3,7 @@ use alloc::vec::Vec; use const_oid::db::rfc5280::ID_CE_POLICY_MAPPINGS; use const_oid::AssociatedOid; use der::asn1::ObjectIdentifier; -use der::Sequence; +use der::{Sequence, ValueOrd}; /// PolicyMappings as defined in [RFC 5280 Section 4.2.1.5]. /// @@ -31,7 +31,7 @@ impl_newtype!(PolicyMappings, Vec); /// ``` /// /// [RFC 5280 Section 4.2.1.5]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.5 -#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[derive(Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] #[allow(missing_docs)] pub struct PolicyMapping { pub issuer_domain_policy: ObjectIdentifier, diff --git a/x509-cert/src/macros.rs b/x509-cert/src/macros.rs index 3256c2425..638d51686 100644 --- a/x509-cert/src/macros.rs +++ b/x509-cert/src/macros.rs @@ -69,5 +69,12 @@ macro_rules! impl_newtype { self.0.value_len() } } + + #[allow(unused_lifetimes)] + impl<'a> ::der::ValueOrd for $newtype { + fn value_cmp(&self, other: &Self) -> ::der::Result<::core::cmp::Ordering> { + self.0.value_cmp(&other.0) + } + } }; } diff --git a/x509-cert/src/time.rs b/x509-cert/src/time.rs index e938c13d0..d1f2ec5d5 100644 --- a/x509-cert/src/time.rs +++ b/x509-cert/src/time.rs @@ -3,7 +3,7 @@ use core::fmt; use core::time::Duration; use der::asn1::{GeneralizedTime, UtcTime}; -use der::{Choice, DateTime, Decode, Error, Result, Sequence}; +use der::{Choice, DateTime, Decode, Error, Result, Sequence, ValueOrd}; #[cfg(feature = "std")] use std::time::SystemTime; @@ -21,7 +21,7 @@ use std::time::SystemTime; /// /// [RFC 5280 Section 4.1.2.5]: https://tools.ietf.org/html/rfc5280#section-4.1.2.5 /// [RFC 5280 Appendix A]: https://tools.ietf.org/html/rfc5280#page-117 -#[derive(Choice, Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Choice, Copy, Clone, Debug, Eq, PartialEq, ValueOrd)] pub enum Time { /// Legacy UTC time (has 2-digit year, valid only through 2050). #[asn1(type = "UTCTime")] @@ -113,7 +113,7 @@ impl TryFrom for Time { /// } /// ``` /// [RFC 5280 Section 4.1.2.5]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.5 -#[derive(Copy, Clone, Debug, Eq, PartialEq, Sequence)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Sequence, ValueOrd)] pub struct Validity { /// notBefore value pub not_before: Time,