# Documentation: BER/DER parsing recipes ## Builtin types Most builtin types can be parsed by calling the `from_der` or `from_der` functions (see `FromBer` and `FromDer` traits for documentation). For ex: ```rust # use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = ::from_der(input)?; # Ok(()) }; ``` Note: this crates makes extensive use of types annotation and turbofish operator, for example `::from_der()` or `TaggedExplicit::::from_der()`. See table B-3 in for reference on syntax. ## `SEQUENCE` and `SET` The `SEQUENCE` and `SET` types are handled very similarly, so recipes will be given for `SEQUENCE`, but can be adapted to `SET` by replacing words. ### Parsing `SEQUENCE` Usually, the sequence envelope does not need to be stored, so it just needs to be parsed to get the sequence content and parse it. The methods [`from_ber_and_then`](crate::Sequence::from_ber_and_then()) and [`from_der_and_then`](crate::Sequence::from_der_and_then()) provide helpers for that: ```rust # use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = Sequence::from_ber_and_then(input, |i| { // first item is INTEGER let (rem, a) = u32::from_der(input)?; // second item is OCTET STRING let (rem, b) = <&[u8]>::from_der(input)?; Ok((rem, (a, b))) })?; // result has type (u32, &[u8]) assert_eq!(result.0, 0); assert_eq!(result.1, b"\x00\x01"); # Ok(()) }; ``` ### Automatically deriving sequence parsers The [`BerSequence`](crate::BerSequence) and [`DerSequence`](crate::DerSequence) custom derive provide attributes to automatically derive a parser for a sequence. For ex: ```rust # use asn1_rs::*; #[derive(DerSequence)] pub struct S { a: u32, b: u16, c: u16, } # let parser = |input| -> Result<(), Error> { let (rem, result) = S::from_der(input)?; # Ok(()) }; ``` This will work for any field type that implements [`FromBer`](crate::FromBer) or [`FromDer`](crate::FromDer), respectively. See [`derive`](mod@derive) documentation for more examples and documentation. ### Parsing `SEQUENCE OF` `SEQUENCE OF T` can be parsed using either type `SequenceOf` or `Vec`: ```rust # use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = SequenceOf::::from_der(input)?; # Ok(()) }; ``` or ```rust # use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = >::from_der(input)?; # Ok(()) }; ``` `SET OF T` can be parsed using either `SetOf`, `BTreeSet` or `HashSet`. ## `EXPLICIT` tagged values ### Parsing `EXPLICIT`, expecting a known tag If you expect only a specific tag, use `TaggedExplicit`. For ex, to parse a `[3] EXPLICIT INTEGER`: ```rust # use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = TaggedExplicit::::from_der(input)?; // result has type TaggedValue. Use `.as_ref()` or `.into_inner()` // to access content let tag = result.tag(); let class = result.class(); assert_eq!(result.as_ref(), &0); # Ok(()) }; ``` ### Specifying the class `TaggedExplicit` does not check the class, and accepts any class. It expects you to check the class after reading the value. To specify the class in the parser, use `TaggedValue`: ```rust # use asn1_rs::*; # let parser = |input| -> Result<(), Error> { // Note: the strange notation (using braces) is required by the compiler to use // a constant instead of the numeric value. let (rem, result) = TaggedValue::::from_der(input)?; # Ok(()) }; ``` Note that `TaggedExplicit` is a type alias to `TaggedValue`, so the objects are the same. ### Accepting any `EXPLICIT` tag To parse a value, accepting any class or tag, use `TaggedParser`. ```rust # use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = TaggedParser::::from_der(input)?; // result has type TaggedParser. Use `.as_ref()` or `.into_inner()` // to access content let tag = result.tag(); let class = result.class(); assert_eq!(result.as_ref(), &0); # Ok(()) }; ``` ### Optional tagged values To parse optional tagged values, `Option>` can be used: ```rust # use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = Option::>::from_der(input)?; # Ok(()) }; ``` The type `OptTaggedExplicit` is also provided as an alias: ```rust # use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = OptTaggedExplicit::::from_der(input)?; # Ok(()) }; ``` ## `IMPLICIT` tagged values ### Parsing `IMPLICIT`, expecting a known tag If you expect only a specific tag, use `TaggedImplicit`. For ex, to parse a `[3] EXPLICIT INTEGER`: ```rust # use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = TaggedExplicit::::from_der(input)?; // result has type TaggedValue. Use `.as_ref()` or `.into_inner()` // to access content let tag = result.tag(); let class = result.class(); assert_eq!(result.as_ref(), &0); # Ok(()) }; ``` ### Specifying the class `TaggedImplicit` does not check the class, and accepts any class. It expects you to check the class after reading the value. To specify the class in the parser, use `TaggedValue`: ```rust # use asn1_rs::*; # let parser = |input| -> Result<(), Error> { // Note: the strange notation (using braces) is required by the compiler to use // a constant instead of the numeric value. let (rem, result) = TaggedValue::::from_der(input)?; # Ok(()) }; ``` Note that `TaggedImplicit` is a type alias to `TaggedValue`, so the objects are the same. ### Accepting any `IMPLICIT` tag To parse a value, accepting any class or tag, use `TaggedParser`. ```rust # use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = TaggedParser::::from_der(input)?; // result has type TaggedParser. Use `.as_ref()` or `.into_inner()` // to access content let tag = result.tag(); let class = result.class(); assert_eq!(result.as_ref(), &0); # Ok(()) }; ``` ### Optional tagged values To parse optional tagged values, `Option>` can be used: ```rust # use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = Option::>::from_der(input)?; # Ok(()) }; ``` The type `OptTaggedImplicit` is also provided as an alias: ```rust # use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = OptTaggedImplicit::::from_der(input)?; # Ok(()) }; ```