# no_std Support
## Feature levels
Synta provides three feature levels:
### 1. no_std (no alloc)
The most minimal configuration, suitable for the most constrained environments.
```toml
[dependencies]
synta = { version = "0.1", default-features = false }
```
Available:
- 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`
```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.
```toml
[dependencies]
synta = { version = "0.1", default-features = false, features = ["alloc"] }
```
Additional features beyond no_std:
- Full SEQUENCE, SET, and constructed type support
- Indefinite length support (for BER)
- Vec-based types (SequenceOf, SetOf)
- String types with dynamic allocation
```rust
#![no_std]
extern crate alloc;
use synta::{Decoder, Encoding};
use synta::types::constructed::Sequence;
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.
```toml
[dependencies]
synta = "0.1" # std is default
```
## Feature comparison
| 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 |
## Derive macro support
Derive macros require proc-macros, which need std at compile time. The `derive`
feature is only available when `std` is enabled.
For derive-like functionality in no_std environments, manually implement the
`Encode`, `Decode`, and `Tagged` traits following the patterns in the library.
## Code generation for no_std
The `--use-core` CLI flag replaces `std::` paths with `core::` equivalents:
```sh
synta-codegen schema.asn1 --use-core -o src/generated.rs
```
Generated code uses `core::convert::TryFrom` instead of `std::convert::TryFrom`.
This is compatible with the no_std configuration.
In `CodeGenConfig`:
```rust
use synta_codegen::CodeGenConfig;
let config = CodeGenConfig {
use_core: true,
..Default::default()
};
```
## Building for embedded targets
```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`
## 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();
bytes.as_ptr() as *mut u8
}
```
## Memory usage notes
### Stack usage (SmallVec optimization)
- Integer: stack-allocated for values up to 16 bytes
- OID: stack-allocated for paths up to 8 components
### 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