1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
|
# 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) = <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.
### 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<T>` or `Vec<T>`:
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
let (rem, result) = SequenceOf::<u32>::from_der(input)?;
# Ok(()) };
```
or
```rust
# 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 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::<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(()) };
```
### 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::<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.
### 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::<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(()) };
```
### Optional tagged values
To parse optional tagged values, `Option<TaggedExplicit<...>>` can be used:
```rust
# 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:
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
let (rem, result) = OptTaggedExplicit::<u32, Error, 0>::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::<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(()) };
```
### 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::<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.
### 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::<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(()) };
```
### Optional tagged values
To parse optional tagged values, `Option<TaggedImplicit<...>>` can be used:
```rust
# 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:
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
let (rem, result) = OptTaggedImplicit::<u32, Error, 0>::from_der(input)?;
# Ok(()) };
```
|