red_asn1 0.4.6

A little library to encode/decode ASN1 DER
Documentation
use crate::error as asn1err;
use crate::tag::Tag;
use crate::traits::Asn1Object;
use std::ops::{Deref, DerefMut};

pub static SET_OF_TAG_NUMBER: u8 = 0x11;

#[derive(Debug, Default, Clone, PartialEq)]
pub struct SetOf<T>(pub Vec<T>);

/// Tag of Set Of
pub fn setof_tag() -> Tag {
    return Tag::new_constructed_universal(SET_OF_TAG_NUMBER);
}

impl<T> Deref for SetOf<T> {
    type Target = Vec<T>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T> DerefMut for SetOf<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl<T: Asn1Object> Asn1Object for SetOf<T> {
    fn tag() -> Tag {
        return setof_tag();
    }

    fn build_value(&self) -> Vec<u8> {
        let mut value: Vec<u8> = Vec::new();
        for item in self.iter() {
            value.append(&mut item.build())
        }
        return value;
    }

    fn parse_value(&mut self, raw: &[u8]) -> asn1err::Result<()> {
        let mut components: Vec<T> = Vec::new();
        let mut raw = raw;

        while !raw.is_empty() {
            let (raw_tmp, component) = T::parse(raw)?;
            raw = raw_tmp;
            components.push(component);
        }

        self.0 = components;
        return Ok(());
    }
}

#[cfg(test)]
mod tests {
    use super::super::integer::{Integer, INTEGER_TAG_NUMBER};
    use super::*;

    #[test]
    fn test_build_set_of_integers() {
        let mut seq_of: SetOf<Integer> = SetOf::default();
        seq_of.push(Integer::from(9));
        seq_of.push(Integer::from(1000));

        assert_eq!(
            vec![
                0x31,
                0x7,
                INTEGER_TAG_NUMBER,
                0x1,
                0x9,
                INTEGER_TAG_NUMBER,
                0x2,
                0x3,
                0xe8
            ],
            seq_of.build()
        );
    }

    #[test]
    fn test_build_empty_set_of() {
        let seq_of: SetOf<Integer> = SetOf::default();

        assert_eq!(vec![0x31, 0x0], seq_of.build());
    }

    #[test]
    fn test_parse_sequence_of_integers() {
        let (_, seq_of) = SetOf::<Integer>::parse(&[
            0x31,
            0x7,
            INTEGER_TAG_NUMBER,
            0x1,
            0x9,
            INTEGER_TAG_NUMBER,
            0x2,
            0x3,
            0xe8,
        ])
        .unwrap();

        assert_eq!(Integer::from(9), seq_of[0]);
        assert_eq!(Integer::from(1000), seq_of[1]);
    }

    #[test]
    fn test_parse_empty_sequence() {
        let (_, seq_of) = SetOf::<Integer>::parse(&[0x31, 0x0]).unwrap();
        assert_eq!(0, seq_of.len());
    }

    #[test]
    fn test_parse_integers_with_excesive_bytes() {
        let raw = [
            0x31,
            0x7,
            INTEGER_TAG_NUMBER,
            0x1,
            0x9,
            INTEGER_TAG_NUMBER,
            0x2,
            0x3,
            0xe8,
            0xff,
            0xff,
        ];
        let (rest, seq_of) = SetOf::<Integer>::parse(&raw).unwrap();

        let x: &[u8] = &[0xff, 0xff];
        assert_eq!(x, rest);
        assert_eq!(Integer::from(9), seq_of[0]);
        assert_eq!(Integer::from(1000), seq_of[1]);
    }

    #[should_panic(expected = "UnmatchedTag")]
    #[test]
    fn test_parse_with_invalid_sequence_of_tag() {
        SetOf::<Integer>::parse(&[0xff, 0x0]).unwrap();
    }

    #[should_panic(expected = "UnmatchedTag")]
    #[test]
    fn test_parse_with_invalid_inner_type_tag() {
        SetOf::<Integer>::parse(&[0x31, 0x3, 0xff, 0x1, 0x9]).unwrap();
    }
}