Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 74 additions & 33 deletions der/derive/src/value_ord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ pub(crate) struct DeriveValueOrd {

/// Fields of structs or enum variants.
fields: Vec<ValueField>,

is_enum: bool,

@tarcieri tarcieri Sep 25, 2022

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this would be semantically clearer as an enum with Struct and Enum variants

}

impl DeriveValueOrd {
Expand All @@ -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: \
Expand All @@ -58,6 +64,7 @@ impl DeriveValueOrd {
ident,
lifetime,
fields,
is_enum,
}
}

Expand All @@ -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
}
}
}
Expand All @@ -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.
Expand All @@ -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),
}
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions der/src/asn1/bit_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,17 @@ impl<T: flagset::Flags> FixedTag for flagset::FlagSet<T> {
const TAG: Tag = BitStringRef::TAG;
}

#[cfg(feature = "flagset")]
impl<T> ValueOrd for flagset::FlagSet<T>
where
T: flagset::Flags,
T::Type: Ord,
{
fn value_cmp(&self, other: &Self) -> Result<Ordering> {
Ok(self.bits().cmp(&other.bits()))
}
}

#[cfg(feature = "flagset")]
#[allow(clippy::integer_arithmetic)]
impl<'a, T> DecodeValue<'a> for flagset::FlagSet<T>
Expand Down
8 changes: 5 additions & 3 deletions der/src/asn1/integer/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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>,
Expand Down Expand Up @@ -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;
Expand Down
13 changes: 10 additions & 3 deletions x509-cert/src/certificate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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].
Expand All @@ -30,6 +31,12 @@ pub enum Version {
V3 = 2,
}

impl ValueOrd for Version {
fn value_cmp(&self, other: &Self) -> der::Result<Ordering> {
(&(*self as u8)).value_cmp(&(*other as u8))
}
}

impl Default for Version {
fn default() -> Self {
Self::V1
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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>,
Expand Down
8 changes: 4 additions & 4 deletions x509-cert/src/crl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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].
Expand All @@ -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>,
Expand All @@ -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>,
Expand All @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions x509-cert/src/ext.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Standardized X.509 Certificate Extensions

use der::Sequence;
use der::{Sequence, ValueOrd};
use spki::ObjectIdentifier;

pub mod pkix;
Expand All @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions x509-cert/src/ext/pkix/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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].
///
Expand Down Expand Up @@ -50,7 +50,7 @@ impl_newtype!(SubjectInfoAccessSyntax<'a>, Vec<AccessDescription<'a>>);
/// ```
///
/// [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,
Expand Down
6 changes: 3 additions & 3 deletions x509-cert/src/ext/pkix/certpolicy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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].
///
Expand Down Expand Up @@ -35,7 +35,7 @@ impl_newtype!(CertificatePolicies<'a>, Vec<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 PolicyInformation<'a> {
pub policy_identifier: ObjectIdentifier,
Expand All @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions x509-cert/src/ext/pkix/crl/dp.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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")]
Expand Down
4 changes: 2 additions & 2 deletions x509-cert/src/ext/pkix/name/dirstr.rs
Original file line number Diff line number Diff line change
@@ -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].
///
Expand Down Expand Up @@ -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")]
Expand Down
Loading