|  | //! Ordering trait. | 
|  |  | 
|  | use crate::{EncodeValue, Result, Tagged}; | 
|  | use core::{cmp::Ordering, marker::PhantomData}; | 
|  |  | 
|  | /// DER ordering trait. | 
|  | /// | 
|  | /// Compares the ordering of two values based on their ASN.1 DER | 
|  | /// serializations. | 
|  | /// | 
|  | /// This is used by the DER encoding for `SET OF` in order to establish an | 
|  | /// ordering for the elements of sets. | 
|  | pub trait DerOrd { | 
|  | /// Return an [`Ordering`] between `self` and `other` when serialized as | 
|  | /// ASN.1 DER. | 
|  | fn der_cmp(&self, other: &Self) -> Result<Ordering>; | 
|  | } | 
|  |  | 
|  | /// DER value ordering trait. | 
|  | /// | 
|  | /// Compares the ordering of the value portion of TLV-encoded DER productions. | 
|  | pub trait ValueOrd { | 
|  | /// Return an [`Ordering`] between value portion of TLV-encoded `self` and | 
|  | /// `other` when serialized as ASN.1 DER. | 
|  | fn value_cmp(&self, other: &Self) -> Result<Ordering>; | 
|  | } | 
|  |  | 
|  | impl<T> DerOrd for T | 
|  | where | 
|  | T: EncodeValue + ValueOrd + Tagged, | 
|  | { | 
|  | fn der_cmp(&self, other: &Self) -> Result<Ordering> { | 
|  | match self.header()?.der_cmp(&other.header()?)? { | 
|  | Ordering::Equal => self.value_cmp(other), | 
|  | ordering => Ok(ordering), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Marker trait for types whose `Ord` impl can be used as `ValueOrd`. | 
|  | /// | 
|  | /// This means the `Ord` impl will sort values in the same order as their DER | 
|  | /// encodings. | 
|  | pub trait OrdIsValueOrd: Ord {} | 
|  |  | 
|  | impl<T> ValueOrd for T | 
|  | where | 
|  | T: OrdIsValueOrd, | 
|  | { | 
|  | fn value_cmp(&self, other: &Self) -> Result<Ordering> { | 
|  | Ok(self.cmp(other)) | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Compare the order of two iterators using [`DerCmp`] on the values. | 
|  | pub(crate) fn iter_cmp<'a, I, T: 'a>(a: I, b: I) -> Result<Ordering> | 
|  | where | 
|  | I: Iterator<Item = &'a T> + ExactSizeIterator, | 
|  | T: DerOrd, | 
|  | { | 
|  | let length_ord = a.len().cmp(&b.len()); | 
|  |  | 
|  | for (value1, value2) in a.zip(b) { | 
|  | match value1.der_cmp(value2)? { | 
|  | Ordering::Equal => (), | 
|  | other => return Ok(other), | 
|  | } | 
|  | } | 
|  |  | 
|  | Ok(length_ord) | 
|  | } | 
|  |  | 
|  | /// Provide a no-op implementation for PhantomData | 
|  | impl<T> ValueOrd for PhantomData<T> { | 
|  | fn value_cmp(&self, _other: &Self) -> Result<Ordering> { | 
|  | Ok(Ordering::Equal) | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Provide a no-op implementation for PhantomData | 
|  | impl<T> DerOrd for PhantomData<T> { | 
|  | fn der_cmp(&self, _other: &Self) -> Result<Ordering> { | 
|  | Ok(Ordering::Equal) | 
|  | } | 
|  | } |