summaryrefslogtreecommitdiff
path: root/src/asn1_types/set/btreeset.rs
diff options
context:
space:
mode:
authorAndrew Walbran <qwandor@google.com>2023-11-21 13:56:20 +0000
committerAndrew Walbran <qwandor@google.com>2023-11-29 11:49:45 +0000
commitd127e38bde91b8a4149b8427b2c5232c42600348 (patch)
treec45f74feaf5a4dc9defc073d4ed21cb2f44fb58d /src/asn1_types/set/btreeset.rs
parentb3f3469fe628561e9f1d9496515dd3f4fb2fb0bf (diff)
downloadasn1-rs-d127e38bde91b8a4149b8427b2c5232c42600348.tar.gz
Import asn1-rs crate.upstream
Request Document: go/android-rust-importing-crates For CL Reviewers: go/android3p#cl-review For Build Team: go/ab-third-party-imports Bug: 312432424 Test: Treehugger Change-Id: I85bc232ad9135f53080ca8b0f5f3458aaf374d38
Diffstat (limited to 'src/asn1_types/set/btreeset.rs')
-rw-r--r--src/asn1_types/set/btreeset.rs124
1 files changed, 124 insertions, 0 deletions
diff --git a/src/asn1_types/set/btreeset.rs b/src/asn1_types/set/btreeset.rs
new file mode 100644
index 0000000..a70f9f9
--- /dev/null
+++ b/src/asn1_types/set/btreeset.rs
@@ -0,0 +1,124 @@
+use crate::*;
+use alloc::collections::BTreeSet;
+use core::convert::TryFrom;
+
+impl<T> Tagged for BTreeSet<T> {
+ const TAG: Tag = Tag::Set;
+}
+
+impl<'a, T> TryFrom<Any<'a>> for BTreeSet<T>
+where
+ T: FromBer<'a>,
+ T: Ord,
+{
+ type Error = Error;
+
+ fn try_from(any: Any<'a>) -> Result<Self> {
+ any.tag().assert_eq(Self::TAG)?;
+ any.header.assert_constructed()?;
+ let items = SetIterator::<T, BerParser>::new(any.data).collect::<Result<BTreeSet<T>>>()?;
+ Ok(items)
+ }
+}
+
+impl<T> CheckDerConstraints for BTreeSet<T>
+where
+ T: CheckDerConstraints,
+{
+ fn check_constraints(any: &Any) -> Result<()> {
+ any.tag().assert_eq(Self::TAG)?;
+ any.header.assert_constructed()?;
+ for item in SetIterator::<Any, DerParser>::new(any.data) {
+ let item = item?;
+ T::check_constraints(&item)?;
+ }
+ Ok(())
+ }
+}
+
+/// manual impl of FromDer, so we do not need to require `TryFrom<Any> + CheckDerConstraints`
+impl<'a, T, E> FromDer<'a, E> for BTreeSet<T>
+where
+ T: FromDer<'a, E>,
+ T: Ord,
+ E: From<Error>,
+{
+ fn from_der(bytes: &'a [u8]) -> ParseResult<'a, Self, E> {
+ let (rem, any) = Any::from_der(bytes).map_err(Err::convert)?;
+ any.tag()
+ .assert_eq(Self::TAG)
+ .map_err(|e| nom::Err::Error(e.into()))?;
+ any.header
+ .assert_constructed()
+ .map_err(|e| nom::Err::Error(e.into()))?;
+ let items = SetIterator::<T, DerParser, E>::new(any.data)
+ .collect::<Result<BTreeSet<T>, E>>()
+ .map_err(nom::Err::Error)?;
+ Ok((rem, items))
+ }
+}
+
+#[cfg(feature = "std")]
+impl<T> ToDer for BTreeSet<T>
+where
+ T: ToDer,
+{
+ fn to_der_len(&self) -> Result<usize> {
+ let mut len = 0;
+ for t in self.iter() {
+ len += t.to_der_len()?;
+ }
+ let header = Header::new(Class::Universal, true, Self::TAG, Length::Definite(len));
+ Ok(header.to_der_len()? + len)
+ }
+
+ fn write_der_header(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
+ let mut len = 0;
+ for t in self.iter() {
+ len += t.to_der_len().map_err(|_| SerializeError::InvalidLength)?;
+ }
+ let header = Header::new(Class::Universal, true, Self::TAG, Length::Definite(len));
+ header.write_der_header(writer).map_err(Into::into)
+ }
+
+ fn write_der_content(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
+ let mut sz = 0;
+ for t in self.iter() {
+ sz += t.write_der(writer)?;
+ }
+ Ok(sz)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::*;
+ use core::convert::TryFrom;
+ use hex_literal::hex;
+ use std::collections::BTreeSet;
+
+ #[test]
+ fn ber_btreeset() {
+ let input = &hex! {"31 06 02 01 00 02 01 01"};
+ let (_, any) = Any::from_ber(input).expect("parsing hashset failed");
+ <BTreeSet<u32>>::check_constraints(&any).unwrap();
+
+ let h = <BTreeSet<u32>>::try_from(any).unwrap();
+
+ assert_eq!(h.len(), 2);
+ }
+
+ #[test]
+ fn der_btreeset() {
+ let input = &hex! {"31 06 02 01 00 02 01 01"};
+ let r: IResult<_, _, Error> = BTreeSet::<u32>::from_der(input);
+ let (_, h) = r.expect("parsing hashset failed");
+
+ assert_eq!(h.len(), 2);
+
+ assert_eq!(h.to_der_len(), Ok(8));
+ let v = h.to_der_vec().expect("could not serialize");
+ let (_, h2) = SetOf::<u32>::from_der(&v).unwrap();
+ assert!(h.iter().eq(h2.iter()));
+ }
+}