Most builtin types can be parsed by calling the from_der
or from_der
functions (see FromBer
and FromDer
traits for documentation).
For ex:
# use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = <u32>::from_der(input)?; # Ok(()) };
Note: this crates makes extensive use of types annotation and turbofish operator, for example <Type>::from_der()
or TaggedExplicit::<u32, Error, 0>::from_der()
.
See table B-3 in https://doc.rust-lang.org/book/appendix-02-operators.html 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.
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
and from_der_and_then
provide helpers for that:
# 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(()) };
The BerSequence
and DerSequence
custom derive provide attributes to automatically derive a parser for a sequence.
For ex:
# 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
or FromDer
, respectively.
See derive
documentation for more examples and documentation.
SEQUENCE OF
SEQUENCE OF T
can be parsed using either type SequenceOf<T>
or Vec<T>
:
# use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = SequenceOf::<u32>::from_der(input)?; # Ok(()) };
or
# use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = <Vec<u32>>::from_der(input)?; # Ok(()) };
SET OF T
can be parsed using either SetOf<T>
, BTreeSet<T>
or HashSet<T>
.
EXPLICIT
tagged valuesEXPLICIT
, expecting a known tagIf you expect only a specific tag, use TaggedExplicit
.
For ex, to parse a [3] EXPLICIT INTEGER
:
# use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = TaggedExplicit::<u32, Error, 0>::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(()) };
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
:
# 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::<u32, Error, Explicit, {Class::CONTEXT_SPECIFIC}, 0>::from_der(input)?; # Ok(()) };
Note that TaggedExplicit
is a type alias to TaggedValue
, so the objects are the same.
EXPLICIT
tagTo parse a value, accepting any class or tag, use TaggedParser
.
# use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = TaggedParser::<Explicit, u32>::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(()) };
To parse optional tagged values, Option<TaggedExplicit<...>>
can be used:
# use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = Option::<TaggedExplicit::<u32, Error, 0>>::from_der(input)?; # Ok(()) };
The type OptTaggedExplicit
is also provided as an alias:
# use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = OptTaggedExplicit::<u32, Error, 0>::from_der(input)?; # Ok(()) };
IMPLICIT
tagged valuesIMPLICIT
, expecting a known tagIf you expect only a specific tag, use TaggedImplicit
.
For ex, to parse a [3] EXPLICIT INTEGER
:
# use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = TaggedExplicit::<u32, Error, 0>::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(()) };
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
:
# 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::<u32, Error, Implicit, { Class::CONTEXT_SPECIFIC }, 1>::from_der(input)?; # Ok(()) };
Note that TaggedImplicit
is a type alias to TaggedValue
, so the objects are the same.
IMPLICIT
tagTo parse a value, accepting any class or tag, use TaggedParser
.
# use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = TaggedParser::<Implicit, u32>::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(()) };
To parse optional tagged values, Option<TaggedImplicit<...>>
can be used:
# use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = Option::<TaggedImplicit::<u32, Error, 0>>::from_der(input)?; # Ok(()) };
The type OptTaggedImplicit
is also provided as an alias:
# use asn1_rs::*; # let parser = |input| -> Result<(), Error> { let (rem, result) = OptTaggedImplicit::<u32, Error, 0>::from_der(input)?; # Ok(()) };