asn1_rs/asn1_types/set/
btreeset.rs

1use crate::*;
2use alloc::collections::BTreeSet;
3use core::{convert::TryFrom, fmt::Debug};
4
5use self::debug::{trace, trace_generic};
6
7impl<T> Tagged for BTreeSet<T> {
8    const TAG: Tag = Tag::Set;
9}
10
11impl<'a, T> TryFrom<Any<'a>> for BTreeSet<T>
12where
13    T: FromBer<'a>,
14    T: Ord,
15{
16    type Error = Error;
17
18    fn try_from(any: Any<'a>) -> Result<Self> {
19        trace_generic(
20            core::any::type_name::<Self>(),
21            "BTreeSet::from_der",
22            |any| {
23                any.tag().assert_eq(Self::TAG)?;
24                any.header.assert_constructed()?;
25                let items =
26                    SetIterator::<T, BerParser>::new(any.data).collect::<Result<BTreeSet<T>>>()?;
27                Ok(items)
28            },
29            any,
30        )
31    }
32}
33
34impl<T> CheckDerConstraints for BTreeSet<T>
35where
36    T: CheckDerConstraints,
37{
38    fn check_constraints(any: &Any) -> Result<()> {
39        any.tag().assert_eq(Self::TAG)?;
40        any.header.assert_constructed()?;
41        for item in SetIterator::<Any, DerParser>::new(any.data) {
42            let item = item?;
43            T::check_constraints(&item)?;
44        }
45        Ok(())
46    }
47}
48
49/// manual impl of FromDer, so we do not need to require `TryFrom<Any> + CheckDerConstraints`
50impl<'a, T, E> FromDer<'a, E> for BTreeSet<T>
51where
52    T: FromDer<'a, E>,
53    T: Ord,
54    E: From<Error> + Debug,
55{
56    fn from_der(bytes: &'a [u8]) -> ParseResult<'a, Self, E> {
57        trace_generic(
58            core::any::type_name::<Self>(),
59            "BTreeSet::from_der",
60            |bytes| {
61                let (rem, any) = trace(core::any::type_name::<Self>(), Any::from_der, bytes)
62                    .map_err(Err::convert)?;
63                any.tag()
64                    .assert_eq(Self::TAG)
65                    .map_err(|e| Err::Error(e.into()))?;
66                any.header
67                    .assert_constructed()
68                    .map_err(|e| Err::Error(e.into()))?;
69                let items = SetIterator::<T, DerParser, E>::new(any.data)
70                    .collect::<Result<BTreeSet<T>, E>>()
71                    .map_err(Err::Error)?;
72                Ok((rem, items))
73            },
74            bytes,
75        )
76    }
77}
78
79#[cfg(feature = "std")]
80impl<T> ToDer for BTreeSet<T>
81where
82    T: ToDer,
83{
84    fn to_der_len(&self) -> Result<usize> {
85        let mut len = 0;
86        for t in self.iter() {
87            len += t.to_der_len()?;
88        }
89        let header = Header::new(Class::Universal, true, Self::TAG, Length::Definite(len));
90        Ok(header.to_der_len()? + len)
91    }
92
93    fn write_der_header(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
94        let mut len = 0;
95        for t in self.iter() {
96            len += t.to_der_len().map_err(|_| SerializeError::InvalidLength)?;
97        }
98        let header = Header::new(Class::Universal, true, Self::TAG, Length::Definite(len));
99        header.write_der_header(writer).map_err(Into::into)
100    }
101
102    fn write_der_content(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
103        let mut sz = 0;
104        for t in self.iter() {
105            sz += t.write_der(writer)?;
106        }
107        Ok(sz)
108    }
109}
110
111#[cfg(test)]
112mod tests {
113    use crate::*;
114    use core::convert::TryFrom;
115    use hex_literal::hex;
116    use std::collections::BTreeSet;
117
118    #[test]
119    fn ber_btreeset() {
120        let input = &hex! {"31 06 02 01 00 02 01 01"};
121        let (_, any) = Any::from_ber(input).expect("parsing hashset failed");
122        <BTreeSet<u32>>::check_constraints(&any).unwrap();
123
124        let h = <BTreeSet<u32>>::try_from(any).unwrap();
125
126        assert_eq!(h.len(), 2);
127    }
128
129    #[test]
130    fn der_btreeset() {
131        let input = &hex! {"31 06 02 01 00 02 01 01"};
132        let r: IResult<_, _, Error> = BTreeSet::<u32>::from_der(input);
133        let (_, h) = r.expect("parsing hashset failed");
134
135        assert_eq!(h.len(), 2);
136
137        assert_eq!(h.to_der_len(), Ok(8));
138        let v = h.to_der_vec().expect("could not serialize");
139        let (_, h2) = SetOf::<u32>::from_der(&v).unwrap();
140        assert!(h.iter().eq(h2.iter()));
141    }
142}