synta 0.1.1

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

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*

- [Feature Levels]#feature-levels
  - [1. no_std (no alloc)]#1-no_std-no-alloc
  - [2. no_std + alloc]#2-no_std-alloc
  - [3. std (default)]#3-std-default
- [Building and Testing]#building-and-testing
  - [Building for no_std]#building-for-no_std
  - [Common Targets]#common-targets
- [Feature Comparison]#feature-comparison
- [Memory Usage]#memory-usage
  - [Stack Usage]#stack-usage
  - [Heap Usage]#heap-usage
- [Common Patterns]#common-patterns
  - [Embedded Systems]#embedded-systems
  - [WebAssembly]#webassembly
- [Derive Macro Support]#derive-macro-support
- [Troubleshooting]#troubleshooting
  - ["Cannot find crate `std`"]#cannot-find-crate-std
  - ["Cannot allocate memory"]#cannot-allocate-memory
  - ["Feature 'alloc' is required"]#feature-alloc-is-required
- [Future Enhancements]#future-enhancements

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

Synta is designed to work in `no_std` environments, making it suitable for embedded systems and other constrained environments.

## Feature Levels

Synta provides three feature levels:

### 1. no_std (no alloc)

The most minimal configuration, suitable for the most constrained environments.

**Features**:
- Zero-copy tag and length parsing
- Primitive types with stack allocation
- Fixed-size types
- SmallVec optimization for Integer and OID types

**Limitations**:
- No dynamic memory allocation
- Limited to types that can be decoded without heap allocation
- No indefinite length support
- Error messages are &'static str

**Cargo.toml**:
```toml
[dependencies]
synta = { version = "0.1", default-features = false }
```

**Example**:
```rust
#![no_std]

use synta::{Decoder, Encoding};
use synta::types::primitive::Integer;

fn decode_integer(data: &[u8]) -> Result<i64, synta::Error> {
    let mut decoder = Decoder::new(data, Encoding::Der);
    let int: Integer = decoder.decode()?;
    int.as_i64()
}
```

### 2. no_std + alloc

Provides full ASN.1 functionality without requiring std.

**Features**:
- All features from no_std
- Dynamic memory allocation via `alloc`
- Full SEQUENCE, SET, and constructed type support
- Indefinite length support (for BER/CER)
- Vec-based types (SequenceOf, SetOf)
- String types with dynamic allocation

**Limitations**:
- Error messages are still simplified (String instead of formatted)
- No std-specific I/O traits

**Cargo.toml**:
```toml
[dependencies]
synta = { version = "0.1", default-features = false, features = ["alloc"] }
```

**Example**:
```rust
#![no_std]
extern crate alloc;

use synta::{Decoder, Encoding};
use synta::types::constructed::Sequence;
use synta::types::primitive::Integer;

fn decode_sequence(data: &[u8]) -> Result<Sequence, synta::Error> {
    let mut decoder = Decoder::new(data, Encoding::Der);
    decoder.decode()
}
```

### 3. std (default)

Full standard library support with all features enabled.

**Features**:
- All features from no_std + alloc
- Detailed error messages with formatting
- std::error::Error trait implementation
- Future: std::io integration

**Cargo.toml**:
```toml
[dependencies]
synta = "0.1"  # std is default
```

## Building and Testing

### Building for no_std

Test that your code builds for no_std using a bare-metal target:

```bash
# Install target
rustup target add thumbv7em-none-eabihf

# Build for no_std (no alloc)
cargo build --target thumbv7em-none-eabihf --no-default-features

# Build for no_std + alloc
cargo build --target thumbv7em-none-eabihf --no-default-features --features alloc
```

### Common Targets

- **ARM Cortex-M**: `thumbv7em-none-eabihf`, `thumbv6m-none-eabi`
- **RISC-V**: `riscv32imac-unknown-none-elf`
- **AVR**: `avr-unknown-gnu-atmega328`

## Feature Comparison

| Feature | no_std | no_std+alloc | std |
|---------|--------|--------------|-----|
| Tag/Length parsing | yes | yes | yes |
| Primitive types | yes | yes | yes |
| SmallVec optimization | yes | yes | yes |
| SEQUENCE/SET | no | yes | yes |
| SequenceOf/SetOf | no | yes | yes |
| String types | Limited | yes | yes |
| Indefinite length | no | yes | yes |
| Derive macros | no | no | yes |
| Detailed errors | no | no | yes |
| std::error::Error | no | no | yes |

## Memory Usage

### Stack Usage

With SmallVec optimization (enabled with `alloc` feature):
- Integer: Stack-allocated for values up to 16 bytes
- OID: Stack-allocated for paths up to 8 components
- Other types: Depends on content

### Heap Usage

When `alloc` is enabled:
- SEQUENCE/SET: Allocate for element storage
- Strings: Allocate for content
- Large integers/OIDs: Spill to heap when exceeding SmallVec capacity

## Common Patterns

### Embedded Systems

```rust
#![no_std]
extern crate alloc;

use synta::{Decoder, Encoding};
use synta::types::primitive::Integer;

// Decode from flash/ROM
fn verify_signature(cert_data: &[u8]) -> Result<(), synta::Error> {
    let mut decoder = Decoder::new(cert_data, Encoding::Der);
    // ... parse certificate structure
    Ok(())
}
```

### WebAssembly

```rust
#![no_std]
extern crate alloc;

use synta::{Encoder, Encoding};
use synta::types::primitive::Integer;

#[no_mangle]
pub extern "C" fn encode_number(value: i64) -> *mut u8 {
    let int = Integer::from(value);
    let mut encoder = Encoder::new(Encoding::Der);
    encoder.encode(&int).unwrap();
    let bytes = encoder.finish().unwrap();
    // Return pointer to wasm host
    // (proper memory management omitted for brevity)
    bytes.as_ptr() as *mut u8
}
```

## Derive Macro Support

**Note**: Derive macros require proc-macros which need std at compile-time. The `derive` feature is only available when the `std` feature is enabled.

If you need derive-like functionality in no_std environments, manually implement the `Encode`, `Decode`, and `Tagged` traits following the patterns in the library.

## Troubleshooting

### "Cannot find crate `std`"

Make sure you're using `#![no_std]` at the crate root and:
```toml
synta = { version = "0.1", default-features = false }
```

### "Cannot allocate memory"

For constrained environments, use types that don't require heap allocation:
- Use Integer with small values (stack-allocated via SmallVec)
- Use fixed-size primitives (Boolean, Null)
- Avoid large SEQUENCE/SET types

### "Feature 'alloc' is required"

Some types require the `alloc` feature:
```toml
synta = { version = "0.1", default-features = false, features = ["alloc"] }
```

## Future Enhancements

- Support for more types in pure no_std mode (without alloc)
- Compile-time maximum sizes for stack allocation
- Const generics for fixed-size SEQUENCE types