Expand description
§ATD (Ahriknow Transfer Data): Position-based Binary Serialization Format
atd is a multi-language binary serialization format and library implementation.
It provides fast, compact binary serialization and deserialization across different programming languages.
§Key Features
- Multi-language support: Consistent implementation across Rust, Zig, Go, Python, Javascript and other languages
- Fast binary serialization for structs/classes in supported languages
- Supports
Option<T>,Vec<T>,HashMap<K,V>,BTreeMap<K,V>, and nested custom types - Fields are identified by tags, not field names or order, enabling flexible schema evolution
- Missing or extra fields in deserialization are handled gracefully if Default is implemented
§Usage Rules
- Tags are required for any field you want to serialize/deserialze. Use the
#[atd(n)]attribute. - Tags must be unique within the same struct. Duplicate tags will cause a compile-time error.
- Fields without tags are ignored during serialization.
- Default values: Any field without a tag or missing in the deserialized data must implement
Default. - Field names and order do not matter on the serialization or deserialization side. Only the tag and type must match.
§Example
use atd::{Deserialize, DeserializeAtd, Serialize, SerializeAtd};
use std::collections::{BTreeMap, HashMap};
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum UserRole {
#[atd(1)]
Admin,
#[atd(2)]
User,
#[atd(3)]
Guest,
#[atd(4)]
Other(
#[atd(1)] i64,
#[atd(2)] String,
#[atd(3)] BTreeMap<String, bool>,
),
#[atd(5)]
Custom {
#[atd(1)]
index: i64,
#[atd(2)]
description: String,
#[atd(3)]
permissions: BTreeMap<String, bool>,
},
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Address {
#[atd(1)]
street: String,
#[atd(2)]
city: String,
#[atd(3)]
zipcode: u32,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct User {
#[atd(1)]
id: u64,
#[atd(2)]
name: String,
#[atd(3)]
age: u8,
#[atd(4)]
is_active: bool,
#[atd(5)]
balance: f64,
#[atd(6)]
scores: Vec<i32>,
#[atd(7)]
metadata: HashMap<String, String>,
#[atd(8)]
tags: Vec<String>,
#[atd(9)]
height: f32,
#[atd(10)]
rating: Option<f32>,
#[atd(11)]
phone: Option<String>,
#[atd(12)]
permissions: HashMap<String, bool>,
#[atd(13)]
data: Vec<u8>,
#[atd(14)]
address: Address, // Nested struct
#[atd(15)]
roles: Vec<UserRole>, // Enum
}
fn main() {
let user = User {
id: 1,
name: "Ahriknow".to_string(),
age: 28,
is_active: true,
balance: 100000000.00,
scores: vec![100, 90, 80],
metadata: {
let mut metadata = HashMap::new();
metadata.insert("team".to_string(), "backend".to_string());
metadata
},
tags: vec!["rust".to_string(), "developer".to_string()],
height: 172.5,
rating: Some(4.8),
phone: None,
permissions: {
let mut permissions = HashMap::new();
permissions.insert("read".to_string(), true);
permissions.insert("write".to_string(), false);
permissions
},
data: vec![1, 2, 3],
address: Address {
street: "xxx".to_string(),
city: "Changchun".to_string(),
zipcode: 123456,
},
roles: vec![
UserRole::Admin,
UserRole::Other(1, "other".to_string(), {
let mut map = BTreeMap::new();
map.insert("write".to_string(), true);
map.insert("read".to_string(), true);
map.insert("delete".to_string(), false);
map
}),
UserRole::Custom {
index: 2,
description: "custom".to_string(),
permissions: {
let mut map = BTreeMap::new();
map.insert("write".to_string(), false);
map.insert("read".to_string(), true);
map.insert("delete".to_string(), false);
map
},
},
],
};
println!("{:#?}", user);
let serialized = user.to_atd();
let deserialized = User::from_atd(&serialized);
assert_eq!(user, deserialized);
println!("✅ Serialization and deserialization successful!");
}§Supported Field Types
- Primitive types:
i8,i16,i32,i64,i128,u8,u16,u32,u64,u128,f32,f64,bool StringOption<T>(nested support)Vec<T>(nested support)HashMap<K,V>andBTreeMap<K,V>- Nested custom types that implement
SerializeandDeserialize