# Synta Usage Guide
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- [Getting Started](#getting-started)
- [Basic Operations](#basic-operations)
- [Decoding a Simple Integer](#decoding-a-simple-integer)
- [Encoding an Integer](#encoding-an-integer)
- [Building and Encoding a Sequence](#building-and-encoding-a-sequence)
- [Working with Different Types](#working-with-different-types)
- [Primitive Types](#primitive-types)
- [Boolean](#boolean)
- [Integer](#integer)
- [OctetString](#octetstring)
- [Object Identifier (OID)](#object-identifier-oid)
- [Enumerated](#enumerated)
- [String Types](#string-types)
- [Time Types](#time-types)
- [Constructed Types](#constructed-types)
- [Sequence (Ordered)](#sequence-ordered)
- [Set (Unordered, DER-sorted)](#set-unordered-der-sorted)
- [SequenceOf and SetOf (Homogeneous)](#sequenceof-and-setof-homogeneous)
- [Tagged Types](#tagged-types)
- [Explicit Tagging](#explicit-tagging)
- [Implicit Tagging](#implicit-tagging)
- [DER vs BER Encoding](#der-vs-ber-encoding)
- [DER (Distinguished Encoding Rules)](#der-distinguished-encoding-rules)
- [BER (Basic Encoding Rules)](#ber-basic-encoding-rules)
- [Indefinite Length (BER only)](#indefinite-length-ber-only)
- [Error Handling](#error-handling)
- [Error Types](#error-types)
- [Common Errors](#common-errors)
- [Best Practices](#best-practices)
- [Decoder Configuration](#decoder-configuration)
- [Performance Tips](#performance-tips)
- [1. Use Appropriate Integer Types](#1-use-appropriate-integer-types)
- [2. Reuse Buffers Where Possible](#2-reuse-buffers-where-possible)
- [3. SmallVec Optimization](#3-smallvec-optimization)
- [4. Benchmarking Your Code](#4-benchmarking-your-code)
- [Serde Integration](#serde-integration)
- [JSON representations](#json-representations)
- [Serializing primitive types](#serializing-primitive-types)
- [Deserializing](#deserializing)
- [DER → JSON → DER round-trip](#der-json-der-round-trip)
- [Serializing an ASN.1 element tree](#serializing-an-asn1-element-tree)
- [Notes](#notes)
- [Common Patterns](#common-patterns)
- [Pattern 1: Parsing Unknown Structures](#pattern-1-parsing-unknown-structures)
- [Pattern 2: Building Complex Structures](#pattern-2-building-complex-structures)
- [Pattern 3: Roundtrip Validation](#pattern-3-roundtrip-validation)
- [Troubleshooting](#troubleshooting)
- [Problem: "UnexpectedTag" Error](#problem-unexpectedtag-error)
- [Problem: "DerViolation" Error](#problem-derviolation-error)
- [Problem: Integer Overflow](#problem-integer-overflow)
- [Problem: Performance Issues](#problem-performance-issues)
- [Problem: Unknown Data Format](#problem-unknown-data-format)
- [Migration from Other Libraries](#migration-from-other-libraries)
- [From `der` (RustCrypto)](#from-der-rustcrypto)
- [From `asn1-rs`](#from-asn1-rs)
- [From `yasna`](#from-yasna)
- [Examples](#examples)
- [Further Reading](#further-reading)
This guide provides practical examples and best practices for using the Synta ASN.1 library.
## Table of Contents
1. [Getting Started](#getting-started)
2. [Basic Operations](#basic-operations)
3. [Working with Different Types](#working-with-different-types)
4. [DER vs BER Encoding](#der-vs-ber-encoding)
5. [Error Handling](#error-handling)
6. [Performance Tips](#performance-tips)
7. [Serde Integration](#serde-integration)
8. [Common Patterns](#common-patterns)
9. [Troubleshooting](#troubleshooting)
10. [Migration from Other Libraries](#migration-from-other-libraries)
## Getting Started
Add Synta to your `Cargo.toml`:
```toml
[dependencies]
synta = "0.1"
```
Basic imports:
```rust
use synta::{Decoder, Encoder, Encoding};
use synta::types::primitive::{Boolean, Integer, Null};
use synta::types::string::OctetString;
use synta::types::constructed::{Element, Sequence};
```
## Basic Operations
### Decoding a Simple Integer
```rust
use synta::{Decoder, Encoding, Integer};
// DER-encoded INTEGER 42
let data = vec![0x02, 0x01, 0x2A];
let mut decoder = Decoder::new(&data, Encoding::Der);
let integer: Integer = decoder.decode()?;
let value = integer.as_i64()?;
assert_eq!(value, 42);
```
### Encoding an Integer
```rust
use synta::{Encoder, Encoding, Integer};
let integer = Integer::from(12345);
let mut encoder = Encoder::new(Encoding::Der);
encoder.encode(&integer)?;
let encoded = encoder.finish()?;
// encoded contains the DER-encoded bytes
```
### Building and Encoding a Sequence
```rust
use synta::types::constructed::{Element, Sequence};
use synta::types::primitive::{Boolean, Integer};
use synta::{Encoder, Encoding};
let mut seq = Sequence::new();
seq.push(Element::Integer(Integer::from(42)));
seq.push(Element::Boolean(Boolean::new(true)));
let mut encoder = Encoder::new(Encoding::Der);
encoder.encode(&seq)?;
let encoded = encoder.finish()?;
```
## Working with Different Types
### Primitive Types
#### Boolean
```rust
use synta::types::primitive::Boolean;
let b = Boolean::new(true);
let value = b.value(); // Returns bool
```
#### Integer
```rust
use synta::types::primitive::Integer;
// Create from different types
let i1 = Integer::from(42i32);
let i2 = Integer::from(12345i64);
let i3 = Integer::from(i128::MAX);
// Convert back
let val: i64 = i1.as_i64()?;
let val: i128 = i3.as_i128()?;
// Access raw bytes
let bytes = i1.as_bytes(); // Big-endian two's complement
```
#### OctetString
```rust
use synta::types::string::OctetString;
let data = vec![0xDE, 0xAD, 0xBE, 0xEF];
let octets = OctetString::new(data);
let bytes = octets.as_bytes(); // Returns &[u8]
let owned = octets.into_vec(); // Consumes and returns Vec<u8>
```
#### Object Identifier (OID)
```rust
use synta::types::oid::ObjectIdentifier;
use std::str::FromStr;
// Create from components
let components = &[1, 2, 840, 113549, 1, 1, 1]; // RSA Encryption
let oid = ObjectIdentifier::new(components)?;
// Create from string notation
let oid2 = ObjectIdentifier::from_str("1.2.840.113549.1.1.1")?;
// Access components
let comps = oid.components(); // Returns &[u32]
// Format as string
let oid_str = oid.to_string(); // "1.2.840.113549.1.1.1"
```
#### Enumerated
`Enumerated` is a thin newtype over `i64` that decodes and encodes with the ASN.1
ENUMERATED tag (`0x0a`). It is used for typed enum-like fields where the numeric
values are defined by a schema (e.g. OCSP `OCSPResponseStatus`, CRL reason codes).
```rust
use synta::types::primitive::Enumerated;
// Construct from an integer value
let e = Enumerated::from_i32(0);
let e = Enumerated::from_i64(2i64);
// Read the wrapped value
let v: i64 = e.as_i64().unwrap();
// Decode from DER (tag 0x0a)
use synta::{Decoder, Encoding};
let der: &[u8] = &[0x0a, 0x01, 0x00]; // ENUMERATED 0
let mut dec = Decoder::new(der, Encoding::Der);
let status: Enumerated = dec.decode().unwrap();
assert_eq!(status.as_i64().unwrap(), 0);
```
### String Types
```rust
use synta::types::string::{Utf8String, PrintableString, IA5String};
// UTF-8 String
let utf8 = Utf8String::new("Hello, World!".to_string());
// Printable String (restricted character set)
let printable = PrintableString::new("Hello World".to_string())?;
// IA5 String (ASCII)
let ia5 = IA5String::new("ASCII only".to_string())?;
```
### Time Types
```rust
use synta::types::time::{UtcTime, GeneralizedTime};
// UTCTime (year, month, day, hour, minute, second)
let utc = UtcTime::new(2023, 2, 23, 12, 0, 0)?;
// GeneralizedTime (year, month, day, hour, minute, second, milliseconds)
let gen = GeneralizedTime::new(2023, 2, 23, 12, 0, 0, None)?;
```
### Constructed Types
#### Sequence (Ordered)
```rust
use synta::types::constructed::{Element, Sequence};
let mut seq = Sequence::new();
seq.push(Element::Integer(Integer::from(1)));
seq.push(Element::Integer(Integer::from(2)));
// Access elements — consuming iteration (lazy decode)
for element in seq {
match element? {
Element::Integer(i) => println!("Integer: {}", i.as_i64()?),
_ => println!("Other type"),
}
}
```
#### Set (Unordered, DER-sorted)
```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)));
// In DER encoding, elements will be sorted lexicographically
```
#### SequenceOf and SetOf (Homogeneous)
```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));
// Access typed elements
for int in seq_of.elements() {
println!("{}", int.as_i64()?);
}
```
### Tagged Types
#### Explicit Tagging
```rust
use synta::types::tagged::ExplicitTag;
use synta::types::primitive::Integer;
// Context-specific [0] EXPLICIT Integer
let tagged = ExplicitTag::context_specific(0, Integer::from(42));
let inner = tagged.inner(); // Access the Integer
let tag = tagged.tag(); // Get the tag
```
#### Implicit Tagging
```rust
use synta::types::tagged::ImplicitTag;
use synta::types::primitive::Integer;
// Context-specific [0] IMPLICIT Integer
let tagged = ImplicitTag::context_specific(0, Integer::from(42));
```
## DER vs BER Encoding
### DER (Distinguished Encoding Rules)
DER is a strict, deterministic subset of BER used in cryptography:
```rust
use synta::{Decoder, Encoder, Encoding, Integer};
// Encoding in DER mode
let value = Integer::from(42i32);
let mut encoder = Encoder::new(Encoding::Der);
encoder.encode(&value)?;
let der_bytes = encoder.finish()?;
// Decoding in DER mode (strict validation)
let mut decoder = Decoder::new(&der_bytes, Encoding::Der);
let decoded = decoder.decode::<Integer>()?;
```
**DER Requirements:**
- Boolean TRUE must be 0xFF (not just non-zero)
- Integers must use minimal encoding (no leading zeros/0xFF)
- Lengths must use shortest form
- SET elements must be sorted
- No indefinite length encoding
### BER (Basic Encoding Rules)
BER is more flexible and allows multiple encodings:
```rust
use synta::{Decoder, Encoding};
// BER mode accepts relaxed encodings
let mut decoder = Decoder::new(&data, Encoding::Ber);
let decoded = decoder.decode::<Integer>()?;
```
**BER Features:**
- Accepts any non-zero value for Boolean TRUE
- Allows indefinite length encoding
- SET elements don't need to be sorted
- More forgiving with leading zeros
### Indefinite Length (BER only)
```rust
use synta::{Decoder, Encoding};
use synta::types::constructed::Sequence;
// BER with indefinite length
// Tag: 0x30, Length: 0x80 (indefinite), Content..., End: 0x00 0x00
let ber_data = vec![
0x30, 0x80, // SEQUENCE, indefinite length
0x02, 0x01, 0x2A, // INTEGER 42
0x00, 0x00, // End-of-contents
];
let mut decoder = Decoder::new(&ber_data, Encoding::Ber);
let seq: Sequence = decoder.decode()?;
```
## Error Handling
### Error Types
All operations return `Result<T, synta::Error>`:
```rust
use synta::Error;
match decoder.decode::<Integer>() {
Ok(integer) => println!("Decoded: {}", integer.as_i64()?),
Err(Error::UnexpectedEof { position }) => {
println!("Unexpected EOF at position {}", position);
}
Err(Error::UnexpectedTag { position, expected, actual }) => {
println!("Wrong tag at {}: expected {:?}, got {:?}",
position, expected, actual);
}
Err(Error::DerViolation { position, reason }) => {
println!("DER violation at {}: {}", position, reason);
}
Err(e) => println!("Other error: {:?}", e),
}
```
### Common Errors
- `UnexpectedEof`: Not enough data to complete decoding
- `UnexpectedTag`: Wrong ASN.1 tag (type mismatch)
- `DerViolation`: Data doesn't comply with DER rules
- `IntegerOverflow`: Integer too large for native type
- `InvalidEncoding`: Malformed ASN.1 data
### Best Practices
```rust
// Use ? operator for propagation
fn parse_data(data: &[u8]) -> synta::Result<Integer> {
let mut decoder = Decoder::new(data, Encoding::Der);
decoder.decode() // Automatically propagates errors
}
// Or handle specific errors
fn parse_with_fallback(data: &[u8]) -> Integer {
let mut decoder = Decoder::new(data, Encoding::Der);
decoder.decode().unwrap_or_else(|e| {
eprintln!("Decode error: {:?}", e);
Integer::from(0) // Default value
})
}
```
## Decoder Configuration
The decoder supports configurable limits to prevent resource-exhaustion attacks on
untrusted input. Pass a `&DecoderConfig` to `Decoder::new_with_config`:
```rust
use synta::{Decoder, DecoderConfig, Encoding};
let data = &[0x02, 0x01, 0x2A_u8];
let config = DecoderConfig {
max_depth: 32, // maximum nesting depth (default: 32)
max_sequence_elements: 10_000, // maximum elements in one SEQUENCE/SET
max_length: 16 * 1024 * 1024, // maximum encoded value length (16 MiB)
};
let mut decoder = Decoder::new_with_config(data, Encoding::Der, &config);
```
The default limits are conservative and suitable for most use-cases. Tighten them
when parsing data from untrusted sources such as network input or uploaded files.
## Performance Tips
### 1. Use Appropriate Integer Types
```rust
use synta::Integer;
// For small integers, conversion is fast
let val: i32 = integer.as_i32()?;
// For large integers, use i128 or keep as Integer
let big = integer.as_i128()?;
```
### 2. Reuse Buffers Where Possible
```rust
use synta::{Decoder, Encoding, Integer};
// Decode multiple values from the same buffer
let mut decoder = Decoder::new(&data, Encoding::Der);
let int1: Integer = decoder.decode()?;
let int2: Integer = decoder.decode()?;
// ... continue decoding
```
### 3. SmallVec Optimization
The library uses SmallVec for integers, keeping values <=16 bytes inline (no heap allocation):
```rust
use synta::Integer;
// These don't allocate:
let i1 = Integer::from(42i32); // 1-4 bytes
let i2 = Integer::from(i64::MAX); // 8 bytes
let i3 = Integer::from(i128::MAX); // 16 bytes
// This allocates:
let huge = Integer::from_bytes(&[0xFF; 32]); // >16 bytes
```
### 4. Benchmarking Your Code
```rust
// See performance.md for baseline metrics
// Tag/length parsing: ~7ns
// Integer decode: ~14ns
// Integer encode: ~31ns
// Sequence operations: ~80-150ns
```
## Serde Integration
The optional `serde` feature adds `Serialize` and `Deserialize` implementations for all
ASN.1 types. Enable it in `Cargo.toml`:
```toml
[dependencies]
synta = { version = "0.1", features = ["serde"] }
serde_json = "1" # or any other serde format crate
```
### JSON representations
| `Boolean` | `true` / `false` |
| `Integer` | lowercase hex string, e.g. `"2a"` |
| `Null` | `null` |
| `Real` | float |
| `OctetString` | lowercase hex string, e.g. `"deadbeef"` |
| `BitString` | `{"bytes":"<hex>","unused_bits":<n>}` |
| Text strings | plain string |
| `ObjectIdentifier` | dotted-decimal string, e.g. `"1.2.840.113549"` |
| `UtcTime` | `"YYMMDDHHMMSSZ"` |
| `GeneralizedTime` | `"YYYYMMDDHHMMSSZ"` or `"YYYYMMDDHHMMSS.mmmZ"` |
| `SequenceOf<T>` | JSON array |
| `Element` | `{"type":"<Name>","value":<value>}` |
| `ExplicitTag<T>` | `{"tag":{...},"value":<value>}` |
### Serializing primitive types
```rust
use synta::{Boolean, Integer, Null, OctetString, ObjectIdentifier};
// Boolean → true / false
let b = Boolean::new(true);
assert_eq!(serde_json::to_string(&b).unwrap(), "true");
// Integer → lowercase hex
let i = Integer::from_i64(255);
assert_eq!(serde_json::to_string(&i).unwrap(), "\"ff\"");
// Null → null
assert_eq!(serde_json::to_string(&Null).unwrap(), "null");
// OctetString → lowercase hex
let os = OctetString::new(vec![0xCA, 0xFE, 0xBA, 0xBE]);
assert_eq!(serde_json::to_string(&os).unwrap(), "\"cafebabe\"");
// ObjectIdentifier → dotted-decimal
let oid = ObjectIdentifier::new(&[1, 2, 840, 113549]).unwrap();
assert_eq!(serde_json::to_string(&oid).unwrap(), "\"1.2.840.113549\"");
```
### Deserializing
```rust
use synta::{Integer, ObjectIdentifier, OctetString};
let i: Integer = serde_json::from_str("\"ff\"").unwrap();
assert_eq!(i.as_i64().unwrap(), 255);
let oid: ObjectIdentifier = serde_json::from_str("\"2.5.4.3\"").unwrap();
assert_eq!(oid.components(), &[2, 5, 4, 3]);
let os: OctetString = serde_json::from_str("\"cafebabe\"").unwrap();
assert_eq!(os.as_bytes(), &[0xCA, 0xFE, 0xBA, 0xBE]);
```
### DER → JSON → DER round-trip
```rust
use synta::{Decoder, Encoder, Encoding, Integer};
// Start with DER-encoded INTEGER 12345
let der = vec![0x02, 0x02, 0x30, 0x39];
let mut decoder = Decoder::new(&der, Encoding::Der);
let value: Integer = decoder.decode().unwrap();
// Serialize to JSON
let json = serde_json::to_string(&value).unwrap(); // "\"3039\""
// Deserialize from JSON
let restored: Integer = serde_json::from_str(&json).unwrap();
// Re-encode to DER — must be identical to the original
let mut encoder = Encoder::new(Encoding::Der);
encoder.encode(&restored).unwrap();
assert_eq!(encoder.finish().unwrap(), der);
```
### Serializing an ASN.1 element tree
`Element` implements `Serialize` (but not `Deserialize`, because its variants carry
borrowed slices that cannot be reconstructed without the original DER buffer). Use
`serde_json::Value` as the deserialization target when you need to round-trip the JSON:
```rust
use synta::{Decoder, Element, Encoding};
let der = [
0x30, 0x09, // SEQUENCE, 9 bytes
0x02, 0x01, 0x01, // INTEGER 1
0x01, 0x01, 0xff, // BOOLEAN TRUE
0x05, 0x00, // NULL
];
let mut decoder = Decoder::new(&der, Encoding::Der);
let element: Element = decoder.decode().unwrap();
// Serialize the whole tree to JSON
let json = serde_json::to_string_pretty(&element).unwrap();
// Deserialize to serde_json::Value (Element cannot implement Deserialize)
let value: serde_json::Value = serde_json::from_str(&json).unwrap();
println!("{}", value["type"]); // "Sequence"
```
### Notes
- `SequenceOf<T>` and `SetOf<T>` implement both `Serialize` and `Deserialize`.
- `ExplicitTag<T>` and `ImplicitTag<T>` implement both `Serialize` and `Deserialize`.
- `Element`, `Sequence`, and `Set` implement `Serialize` only (borrowed lifetimes prevent
`Deserialize`).
## Common Patterns
### Pattern 1: Parsing Unknown Structures
```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::Integer(i) => println!("Integer: {}", i.as_i64()?),
Element::OctetString(o) => println!("OctetString: {} bytes", o.as_bytes().len()),
Element::Sequence(s) => {
let elements = s.into_elements()?;
println!("Sequence with {} elements", elements.len());
for _elem in &elements {
// Recursively process
}
}
_ => println!("Other type"),
}
Ok(())
}
```
### Pattern 2: Building Complex Structures
```rust
use synta::*;
use synta::types::string::Utf8StringRef;
use synta::types::constructed::Sequence;
fn build_certificate_info() -> Sequence<'static> {
let mut seq = Sequence::new();
// Version
seq.push(Element::Integer(Integer::from(3)));
// Serial number
seq.push(Element::Integer(Integer::from(123456)));
// Subject (Utf8StringRef borrows from a &'static str literal)
let mut subject = Sequence::new();
subject.push(Element::Utf8String(Utf8StringRef::new("Example")));
seq.push(Element::Sequence(subject));
seq
}
```
### Pattern 3: Roundtrip Validation
```rust
fn validate_roundtrip<T>(value: &T) -> synta::Result<bool>
where
T: synta::Encode + for<'a> synta::Decode<'a> + PartialEq,
{
// Encode
let mut encoder = Encoder::new(Encoding::Der);
encoder.encode(value)?;
let encoded = encoder.finish()?;
// Decode
let mut decoder = Decoder::new(&encoded, Encoding::Der);
let decoded: T = decoder.decode()?;
// Compare
Ok(value == &decoded)
}
```
## Troubleshooting
### Problem: "UnexpectedTag" Error
**Cause**: Trying to decode wrong type or data is corrupted.
**Solution**:
```rust
use synta::Element;
// Check what tag is actually there
let tag = decoder.peek_tag()?;
println!("Found tag: {:?}", tag);
// Or use Element for dynamic parsing
let element: Element = decoder.decode()?;
```
**Debug with asn1parse**:
```bash
# Inspect the ASN.1 structure to see what's actually there (text mode)
synta-tool asn1parse myfile.der
# OpenSSL-compatible output for side-by-side comparison
synta-tool asn1parse myfile.der --mode openssl
openssl asn1parse -in myfile.der -inform DER
```
### Problem: "DerViolation" Error
**Cause**: Data doesn't comply with strict DER rules.
**Solution**: Try BER mode if you're parsing non-DER data:
```rust
use synta::{Decoder, Encoding};
let mut decoder = Decoder::new(&data, Encoding::Ber);
```
### Problem: Integer Overflow
**Cause**: Integer value too large for requested type.
**Solution**:
```rust
use synta::Integer;
// Use larger type
let val = integer.as_i128()?; // Instead of as_i64()
// Or keep as Integer
let bytes = integer.as_bytes();
```
### Problem: Performance Issues
**Cause**: Inefficient encoding/decoding patterns.
**Solution**:
- Decode multiple values from one decoder (reuse buffer)
- Use appropriate integer types (don't convert to i128 if i32 suffices)
- Profile with `cargo bench -p synta-bench` to identify bottlenecks
### Problem: Unknown Data Format
**Cause**: Need to understand what's in an ASN.1 file.
**Solution**: Use the `synta-tool asn1parse` command to inspect the structure:
```bash
# Parse and display ASN.1 tree (text mode — shows decoded strings with hex)
synta-tool asn1parse file.pem
# Parse hex-encoded bytes (continuous, space/colon-separated, or hexdump format)
# OpenSSL-compatible one-line-per-element output
synta-tool asn1parse file.pem --mode openssl
```
## Migration from Other Libraries
### From `der` (RustCrypto)
```rust
// der crate
use der::{Decode, Encode};
let value = MyType::from_der(bytes)?;
// Synta
use synta::{Decoder, Encoding};
let mut decoder = Decoder::new(bytes, Encoding::Der);
let value: MyType = decoder.decode()?;
```
### From `asn1-rs`
```rust
// asn1-rs
use asn1_rs::FromDer;
let (rem, value) = MyType::from_der(bytes)?;
// Synta
let mut decoder = Decoder::new(bytes, Encoding::Der);
let value: MyType = decoder.decode()?;
// decoder.is_empty() checks if fully consumed
```
### From `yasna`
```rust
// yasna
use yasna;
let value = yasna::decode_der(bytes, |reader| {
reader.read_sequence(|r| {
// manual parsing
})
})?;
// Synta
let mut decoder = Decoder::new(bytes, Encoding::Der);
let seq: Sequence = decoder.decode()?;
// Work with strongly-typed Sequence
```
## Examples
See the `examples/` directory for complete working examples:
- `decode_integer.rs` - Integer encoding/decoding
- `encode_sequence.rs` - Building and encoding sequences
- `oid_usage.rs` - Working with Object Identifiers
- `parse_certificate.rs` - Parsing X.509 certificate structure
- `serde_usage.rs` - JSON serialization of all ASN.1 types (requires `serde` feature)
- `serde_cert.rs` - Parse a PEM certificate, serialize to JSON, compare trees (requires `serde` feature)
Run examples with:
```bash
cargo run --example decode_integer
cargo run --example encode_sequence
cargo run --example oid_usage
cargo run --example parse_certificate
cargo run --example serde_usage --features serde
cargo run --example serde_cert --features serde
```
## Further Reading
- [performance.md](performance.md) - Performance benchmarks and optimization tips
- [API Documentation](https://docs.rs/synta) - Complete API reference
- [ITU-T X.690](https://www.itu.int/rec/T-REC-X.690) - ASN.1 encoding rules specification