Skip to main content

Crate asun

Crate asun 

Source
Expand description

§ASUN — Array-Schema Unified Notation

A high-performance, token-efficient data format that separates a record’s schema from its data. Where JSON repeats every field name in every record, ASUN declares the field names once and streams the values as compact tuples — smaller payloads, fewer LLM tokens, and faster parsing.

JSON:  [{"id":1,"name":"Alice","active":true},
        {"id":2,"name":"Bob","active":false}]

ASUN:  [{id,name,active}]:(1,Alice,true),(2,Bob,false)

The crate is serde-free. Types opt in with the crate’s own derive macros, #[derive(AsunEncode, AsunDecode)], which generate direct, allocation-lean implementations of the four runtime traits — no visitor indirection.

§Formats

ASUN has two wire formats, both driven by the same derives:

  • Text — self-describing {schema}:(data) (single value) or [{schema}]:rows (sequence). Human-readable and diff-friendly. Optionally carries scalar type hints ({id@int,name@str}).
  • Binary — compact, schema-less, fixed field order. Supports zero-copy decoding: &str fields borrow directly from the input buffer.

§Quick start

use asun::{AsunEncode, AsunDecode, encode, decode, encode_binary, decode_binary};

#[derive(Debug, PartialEq, AsunEncode, AsunDecode)]
struct User {
    id: i64,
    name: String,
    active: bool,
}

let user = User { id: 1, name: "Alice".into(), active: true };

// Text
let text = encode(&user)?;
assert_eq!(text, "{id,name,active}:(1,Alice,true)");
let back: User = decode(&text)?;
assert_eq!(back, user);

// Binary (byte-for-byte stable, zero-copy decode)
let bytes = encode_binary(&user)?;
let back: User = decode_binary(&bytes)?;
assert_eq!(back, user);

§Zero-copy decoding

Give the type a lifetime and the derive will borrow &str fields straight out of the input instead of allocating a String per field — roughly twice as fast on string-heavy payloads.

use asun::{AsunDecode, decode};

#[derive(Debug, PartialEq, AsunDecode)]
struct UserRef<'a> {
    id: i64,
    name: &'a str,
}

let text = String::from("{id,name}:(1,Alice)");
let user: UserRef = decode(&text)?;
assert_eq!(user.name, "Alice");

An escaped string cannot be borrowed (it has to be rebuilt), so &str fields reject those inputs; use String when escapes are expected.

§Untrusted input

Decoding is bounded: nesting deeper than decode::MAX_DEPTH is rejected rather than allowed to exhaust the stack, and the internal schema cache is per-thread and capacity-limited so a stream of distinct schemas cannot grow it without limit.

§API surface

FunctionPurpose
encode() / encode_typed()Encode a value to text (plain / type-hinted schema)
decode()Decode a value from text
encode_pretty() / encode_pretty_typed()Multi-line pretty text
encode_binary() / decode_binary()Encode / decode the binary format

§Field attributes

Fields (and enum variants) accept #[asun(...)] attributes, aligned with serde where the format allows:

  • #[asun(rename = "wire_name")] — override the field/variant name on the wire.
  • #[asun(skip)] — never written, never read; decodes to its default.
  • #[asun(skip_serializing)] — not written; still read when present in text.
  • #[asun(skip_deserializing)] — not read; always decodes to its default.
  • #[asun(skip_serializing_if = "path")] — omit from text when the predicate returns true. Ignored by the binary format (it always writes the field, to keep fixed-order decoding reliable).
  • #[asun(default = "path")] — value source for a field skipped on decode; falls back to Default::default when absent.

Binary skipping is always symmetric: because the binary format has no schema and reads fields in declaration order, a field skipped on one side is skipped on both. See the derive crate docs for the full semantics table.

The derive macros in asun-derive emit fully-qualified ::asun::... paths so downstream crates can use them unambiguously. Inside this crate, alias self as asun so those same paths resolve when we derive on our own test types.

Re-exports§

pub use binary::decode_binary;
pub use binary::decode_binary_exact;
pub use binary::encode_binary;
pub use binary::encode_binary_into;
pub use binary::DEFAULT_MAX_SEQUENCE_LEN;
pub use decode::decode;
pub use encode::encode;
pub use encode::encode_typed;
pub use error::Error;
pub use error::Result;
pub use pretty::encode_pretty;
pub use pretty::encode_pretty_typed;
pub use pretty::pretty_format;
pub use traits::AsunDecode;
pub use traits::AsunDecodeBinary;
pub use traits::AsunEncode;
pub use traits::AsunEncodeBinary;

Modules§

binary
ASUN binary format (ASUN-BIN).
decode
ASUN text decoding.
encode
ASUN text encoding.
error
Error and result types for ASUN encoding and decoding.
pretty
Pretty-printed ASUN text — smart indentation over the compact encoders.
simd
Cross-platform SIMD utilities for accelerating ASUN parsing and serialization.
traits
Core traits for the ASUN format: AsunEncode / AsunDecode (text) and AsunEncodeBinary / AsunDecodeBinary (binary).

Derive Macros§

AsunDecode
Derive macros for the asun encode/decode traits.
AsunEncode
Derive macros for the asun encode/decode traits.