synta 0.1.9

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
//! Example: Building and encoding ASN.1 sequences
//!
//! This example demonstrates how to build complex ASN.1 structures
//! using sequences and encode them to DER format.
//!
//! Run with: cargo run --example encode_sequence

use synta::{Boolean, Decoder, Element, Encoding, Integer, OctetStringRef, Sequence, ToDer};

fn main() {
    println!("=== ASN.1 Sequence Encoding Example ===\n");

    // Example 1: Simple sequence with different types
    simple_sequence();

    // Example 2: Nested sequences
    nested_sequence();

    // Example 3: Sequence roundtrip
    roundtrip_example();
}

fn simple_sequence() {
    println!("Example 1: Simple Sequence");
    println!("--------------------------");

    // Create a sequence with multiple elements
    let mut seq = Sequence::new();
    let octet_data = vec![0xDE, 0xAD, 0xBE, 0xEF];
    seq.push(Element::Integer(Integer::from(42)));
    seq.push(Element::Boolean(Boolean::new(true)));
    seq.push(Element::OctetString(OctetStringRef::new(&octet_data)));

    println!("Created sequence with {} elements", seq.iter().count());

    let encoded = seq.to_der().unwrap();
    println!("Encoded to {} bytes: {:02X?}", encoded.len(), encoded);
    println!();
}

fn nested_sequence() {
    println!("Example 2: Nested Sequences");
    println!("---------------------------");

    // Create an inner sequence
    let mut inner = Sequence::new();
    inner.push(Element::Integer(Integer::from(1)));
    inner.push(Element::Integer(Integer::from(2)));
    inner.push(Element::Integer(Integer::from(3)));

    // Create outer sequence containing the inner one
    let mut outer = Sequence::new();
    outer.push(Element::Sequence(inner));
    outer.push(Element::Integer(Integer::from(100)));

    println!("Created nested structure");

    let encoded = outer.to_der().unwrap();
    println!("Encoded to {} bytes: {:02X?}", encoded.len(), encoded);

    // Parse the structure
    println!("\nParsing structure:");
    println!("  Tag: 0x{:02X} (SEQUENCE)", encoded[0]);
    println!("  Length: {} bytes", encoded[1]);
    println!();
}

fn roundtrip_example() {
    println!("Example 3: Roundtrip Encoding/Decoding");
    println!("--------------------------------------");

    // Create a complex structure
    let mut seq = Sequence::new();
    seq.push(Element::Integer(Integer::from(12345)));
    seq.push(Element::Boolean(Boolean::new(false)));
    seq.push(Element::Integer(Integer::from(-67890)));

    println!("Original sequence:");
    println!("  Element 1: Integer(12345)");
    println!("  Element 2: Boolean(false)");
    println!("  Element 3: Integer(-67890)");

    // Encode
    let encoded = seq.to_der().unwrap();
    println!("\nEncoded: {} bytes", encoded.len());

    // Decode — Sequence<'_> borrows from the input buffer, so use Decoder directly
    let mut decoder = Decoder::new(&encoded, Encoding::Der);
    let decoded: Sequence = decoder.decode().unwrap();

    println!("\nDecoded sequence:");
    for (i, element) in decoded.into_elements().unwrap().iter().enumerate() {
        match element {
            Element::Integer(int) => {
                println!("  Element {}: Integer({})", i + 1, int.as_i64().unwrap())
            }
            Element::Boolean(b) => println!("  Element {}: Boolean({})", i + 1, b.value()),
            _ => println!("  Element {}: {:?}", i + 1, element),
        }
    }

    println!("\nRoundtrip successful!");
    println!();
}