From 1df708192c3196c11ea821eb078d46a24d57e37c Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 29 Jan 2022 14:47:00 -0700 Subject: [PATCH] der: impl `ValueOrd` for `SetOf` and `SetOfVec` Adds impls which make it possible to compare the DER encoded orderings of `SET OF` types. --- der/src/arrayvec.rs | 7 +++++++ der/src/asn1/sequence_of.rs | 28 +++++++--------------------- der/src/asn1/set_of.rs | 26 ++++++++++++++++++++++++-- der/src/ord.rs | 18 ++++++++++++++++++ 4 files changed, 56 insertions(+), 23 deletions(-) diff --git a/der/src/arrayvec.rs b/der/src/arrayvec.rs index b8a10907f..83b6316b2 100644 --- a/der/src/arrayvec.rs +++ b/der/src/arrayvec.rs @@ -121,4 +121,11 @@ impl<'a, T> Iterator for Iter<'a, T> { None } } + + fn size_hint(&self) -> (usize, Option) { + let len = self.elements.len() - self.position; + (len, Some(len)) + } } + +impl<'a, T> ExactSizeIterator for Iter<'a, T> {} diff --git a/der/src/asn1/sequence_of.rs b/der/src/asn1/sequence_of.rs index e378f139b..c44559951 100644 --- a/der/src/asn1/sequence_of.rs +++ b/der/src/asn1/sequence_of.rs @@ -1,8 +1,8 @@ //! ASN.1 `SEQUENCE OF` support. use crate::{ - arrayvec, ArrayVec, Decodable, DecodeValue, Decoder, DerOrd, Encodable, EncodeValue, Encoder, - ErrorKind, FixedTag, Length, Result, Tag, ValueOrd, + arrayvec, ord::iter_cmp, ArrayVec, Decodable, DecodeValue, Decoder, DerOrd, Encodable, + EncodeValue, Encoder, ErrorKind, FixedTag, Length, Result, Tag, ValueOrd, }; use core::cmp::Ordering; @@ -109,7 +109,7 @@ where T: DerOrd, { fn value_cmp(&self, other: &Self) -> Result { - value_cmp(self.iter(), other.iter()) + iter_cmp(self.iter(), other.iter()) } } @@ -128,6 +128,8 @@ impl<'a, T> Iterator for SequenceOfIter<'a, T> { } } +impl<'a, T> ExactSizeIterator for SequenceOfIter<'a, T> {} + impl<'a, T, const N: usize> DecodeValue<'a> for [T; N] where T: Decodable<'a>, @@ -166,7 +168,7 @@ where T: DerOrd, { fn value_cmp(&self, other: &Self) -> Result { - value_cmp(self.iter(), other.iter()) + iter_cmp(self.iter(), other.iter()) } } @@ -225,22 +227,6 @@ where T: DerOrd, { fn value_cmp(&self, other: &Self) -> Result { - value_cmp(self.iter(), other.iter()) + iter_cmp(self.iter(), other.iter()) } } - -/// Compare two `SEQUENCE OF`s by value. -fn value_cmp<'a, I, T: 'a>(a: I, b: I) -> Result -where - I: Iterator, - T: DerOrd, -{ - for (value1, value2) in a.zip(b) { - match value1.der_cmp(value2)? { - Ordering::Equal => (), - other => return Ok(other), - } - } - - Ok(Ordering::Equal) -} diff --git a/der/src/asn1/set_of.rs b/der/src/asn1/set_of.rs index 9bcfdde93..bbb9af11b 100644 --- a/der/src/asn1/set_of.rs +++ b/der/src/asn1/set_of.rs @@ -1,8 +1,8 @@ //! ASN.1 `SET OF` support. use crate::{ - arrayvec, ArrayVec, Decodable, DecodeValue, Decoder, DerOrd, Encodable, EncodeValue, Encoder, - ErrorKind, FixedTag, Length, Result, Tag, + arrayvec, ord::iter_cmp, ArrayVec, Decodable, DecodeValue, Decoder, DerOrd, Encodable, + EncodeValue, Encoder, ErrorKind, FixedTag, Length, Result, Tag, ValueOrd, }; use core::cmp::Ordering; @@ -126,6 +126,15 @@ where const TAG: Tag = Tag::Set; } +impl ValueOrd for SetOf +where + T: Clone + DerOrd, +{ + fn value_cmp(&self, other: &Self) -> Result { + iter_cmp(self.iter(), other.iter()) + } +} + /// Iterator over the elements of an [`SetOf`]. #[derive(Clone, Debug)] pub struct SetOfIter<'a, T> { @@ -141,6 +150,8 @@ impl<'a, T> Iterator for SetOfIter<'a, T> { } } +impl<'a, T> ExactSizeIterator for SetOfIter<'a, T> {} + /// ASN.1 `SET OF` backed by a [`Vec`]. /// /// This type implements an append-only `SET OF` type which is heap-backed @@ -255,3 +266,14 @@ where { const TAG: Tag = Tag::Set; } + +#[cfg(feature = "alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] +impl ValueOrd for SetOfVec +where + T: Clone + DerOrd, +{ + fn value_cmp(&self, other: &Self) -> Result { + iter_cmp(self.iter(), other.iter()) + } +} diff --git a/der/src/ord.rs b/der/src/ord.rs index cfb0ff332..fd967bf88 100644 --- a/der/src/ord.rs +++ b/der/src/ord.rs @@ -51,3 +51,21 @@ where 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 +where + I: Iterator + 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) +}