synta 0.2.6

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
# Constructed Types

## SEQUENCE

A SEQUENCE is an ordered collection of elements of potentially different types.
Its DER tag is `0x30`.

```rust
use synta::types::constructed::{Element, Sequence};
use synta::types::primitive::{Boolean, Integer};

// Build
let mut seq = Sequence::new();
seq.push(Element::Integer(Integer::from(1)));
seq.push(Element::Boolean(Boolean::new(true)));

// Decode
let mut decoder = Decoder::new(&data, Encoding::Der);
let seq: Sequence = decoder.decode()?;

// Consuming iteration (lazy decode)
for element in seq {
    match element? {
        Element::Integer(i)     => println!("Integer: {}", i.as_i64()?),
        Element::Boolean(b)     => println!("Boolean: {}", b.value()),
        Element::OctetString(o) => println!("OctetString: {} bytes", o.as_bytes().len()),
        _ => {}
    }
}
```

## SET

A SET is similar to SEQUENCE but elements are unordered on the wire.  In DER,
SET elements are encoded in sorted order (by DER encoding of each element).
Its tag is `0x31`.

```rust
use synta::types::constructed::{Element, Set};

let mut set = Set::new();
set.push(Element::Integer(Integer::from(10)));
set.push(Element::Integer(Integer::from(5)));
// DER encoder sorts elements lexicographically
```

## SEQUENCE OF

A `SEQUENCE OF T` is a homogeneous ordered collection of elements of type `T`.
Generated as `Vec<T>` — encodes with tag `0x30`.

```rust
use synta::types::constructed::SequenceOf;
use synta::types::primitive::Integer;

let mut seq_of = SequenceOf::<Integer>::new();
seq_of.push(Integer::from(1));
seq_of.push(Integer::from(2));
seq_of.push(Integer::from(3));

for int in seq_of.elements() {
    println!("{}", int.as_i64()?);
}
```

## SET OF

A `SET OF T` is a homogeneous unordered collection.  Generated as `SetOf<T>` —
encodes with tag `0x31`.

```rust
use synta::SetOf;
use synta::types::primitive::Integer;

let mut set_of = SetOf::<Integer>::new();
set_of.push(Integer::from(3));
set_of.push(Integer::from(1));
// DER encoder sorts elements by their encoded form
```

## CHOICE

CHOICE is an enumeration of alternative types; exactly one alternative is
present on the wire.  Generated types use a Rust `enum`:

```asn1
Value ::= CHOICE {
    integer  INTEGER,
    text     UTF8String
}
```

Generated:

```rust
pub enum Value {
    Integer(synta::Integer),
    Text(synta::Utf8String),
}
```

Usage:

```rust
let value: Value = decoder.decode()?;
match value {
    Value::Integer(i) => println!("integer: {}", i.as_i64()?),
    Value::Text(s)    => println!("text: {}", s.as_str()),
}
```

## Element — dynamic type dispatch

`Element` represents any ASN.1 value without a statically known type.  Use it
when the type is only known at runtime or for schema-less parsing.

```rust
use synta::types::constructed::Element;

let element: Element = decoder.decode()?;

match element {
    Element::Integer(i)     => {},
    Element::Boolean(b)     => {},
    Element::OctetString(o) => {},
    Element::BitString(bs)  => {},
    Element::ObjectIdentifier(oid) => {},
    Element::Null(n)        => {},
    Element::Utf8String(s)  => {},
    Element::Sequence(seq)  => {
        let elems = seq.into_elements()?;
        // recursively process
    }
    Element::Set(set)       => {},
    Element::Tagged(tag, inner) => {},
    _ => {},
}
```

## SeqRepr and lazy element parsing

`Sequence` and `Set` use a lazy internal representation.  A freshly decoded
`Sequence` stores the raw DER span (`SeqRepr::Borrowed`); elements are only
parsed when iteration begins.  This means decoding a large SEQUENCE is O(1) —
the full content is not parsed until you iterate.

```rust
// O(1) — only reads the SEQUENCE tag and length
let seq: Sequence = decoder.decode()?;

// Parsing happens here, on first iteration
for element in seq {
    let elem = element?;
    // ...
}
```

## Nested sequence pattern

```rust
use synta::types::constructed::Element;

fn parse_unknown(data: &[u8]) -> synta::Result<()> {
    let mut decoder = Decoder::new(data, Encoding::Der);
    let element: Element = decoder.decode()?;

    match element {
        Element::Sequence(s) => {
            let elements = s.into_elements()?;
            println!("Sequence with {} elements", elements.len());
            for elem in &elements {
                // process each element
            }
        }
        _ => {}
    }
    Ok(())
}
```

## Roundtrip: encode then decode

```rust
use synta::types::constructed::{Element, Sequence};
use synta::types::primitive::Integer;
use synta::{Encoder, Decoder, Encoding};

// Build and encode
let mut seq = Sequence::new();
seq.push(Element::Integer(Integer::from(42)));

let mut encoder = Encoder::new(Encoding::Der);
encoder.encode(&seq)?;
let encoded = encoder.finish()?;

// Decode
let mut decoder = Decoder::new(&encoded, Encoding::Der);
let decoded: Sequence = decoder.decode()?;
```