Rust Serialization Guide
Apache Fory™ is a blazing fast multi-language serialization framework powered by JIT compilation and zero-copy techniques, providing up to ultra-fast performance while maintaining ease of use and safety.
The Rust implementation provides versatile and high-performance serialization with automatic memory management and compile-time type safety. It supports both xlang mode for cross-language payloads and native mode for Rust-only payloads.
Why Apache Fory™ Rust?
- Fast binary encoding: Zero-copy deserialization and optimized binary protocols
- Xlang: Seamlessly serialize/deserialize data across Java, Python, C++, Go, JavaScript, and Rust
- Type-safe: Compile-time type checking with derive macros
- Circular references: Automatic tracking of shared and circular references with
Rc/Arcand weak pointers - Polymorphic: Serialize trait objects with
Box<dyn Trait>,Rc<dyn Trait>, andArc<dyn Trait> - Schema evolution: Compatible mode for independent schema changes
- Two formats: Object graph serialization and zero-copy row-based format
Crates
| Crate | Description | Version |
|---|---|---|
fory | High-level API with derive macros | |
fory-core | Core serialization engine | |
fory-derive | Procedural macros |
Quick Start
Add Apache Fory™ to your Cargo.toml:
[dependencies]
fory = "1.0.0"
Basic Example
use fory::{Fory, Error, Reader};
use fory::ForyStruct;
#[derive(ForyStruct, Debug, PartialEq)]
struct User {
name: String,
age: i32,
email: String,
}
fn main() -> Result<(), Error> {
let mut fory = Fory::builder().xlang(true).build();
fory.register::<User>(1)?;
let user = User {
name: "Alice".to_string(),
age: 30,
email: "alice@example.com".to_string(),
};
// Serialize
let bytes = fory.serialize(&user)?;
// Deserialize
let decoded: User = fory.deserialize(&bytes)?;
assert_eq!(user, decoded);
// Serialize to specified buffer
let mut buf: Vec<u8> = vec![];
fory.serialize_to(&mut buf, &user)?;
// Deserialize from specified buffer
let mut reader = Reader::new(&buf);
let decoded: User = fory.deserialize_from(&mut reader)?;
assert_eq!(user, decoded);
Ok(())
}
Xlang Mode And Native Mode
Use xlang mode for cross-language payloads and schemas shared with other Fory runtimes. Xlang mode is the default Rust wire mode, and Rust examples that use it set .xlang(true) explicitly so the mode choice is visible.
Use native mode for Rust-only traffic. Native mode is selected with .xlang(false), uses schema-consistent payloads unless compatible mode is enabled, and keeps Rust object serialization on the Rust runtime path. It is optimized for Rust's type system and covers Rust-specific object features such as trait objects and shared-reference patterns that are not portable xlang payloads.
See Xlang Serialization for Rust xlang registration and interoperability rules, and Native Serialization for Rust-only payloads.
Thread Safety
Apache Fory™ Rust is fully thread-safe: Fory implements both Send and Sync, so one configured instance can be shared across threads for concurrent work. The internal read/write context pools are lazily initialized with thread-safe primitives, letting worker threads reuse buffers without coordination.
use fory::{Fory, Error};
use fory::ForyStruct;
use std::sync::Arc;
use std::thread;
#[derive(ForyStruct, Clone, Copy, Debug, PartialEq)]
struct Item {
value: i32,
}
fn main() -> Result<(), Error> {
let mut fory = Fory::builder().xlang(true).build();
fory.register::<Item>(1000)?;
let fory = Arc::new(fory);
let handles: Vec<_> = (0..8)
.map(|i| {
let shared = Arc::clone(&fory);
thread::spawn(move || {
let item = Item { value: i };
shared.serialize(&item)
})
})
.collect();
for handle in handles {
let bytes = handle.join().unwrap()?;
let item: Item = fory.deserialize(&bytes)?;
assert!(item.value >= 0);
}
Ok(())
}
Tip: Perform registrations (such as fory.register::<T>(id)) before spawning threads so every worker sees the same metadata. Once configured, wrapping the instance in Arc is enough to fan out serialization and deserialization tasks safely.
Architecture
The Rust implementation consists of three main crates:
fory/ # High-level API
├── src/lib.rs # Public API exports
fory-core/ # Core serialization engine
├── src/
│ ├── fory.rs # Main serialization entry point
│ ├── buffer.rs # Binary buffer management
│ ├── serializer/ # Type-specific serializers
│ ├── resolver/ # Type resolution and metadata
│ ├── meta/ # Meta string compression
│ ├── row/ # Row format implementation
│ └── types.rs # Type definitions
fory-derive/ # Procedural macros
├── src/
│ ├── object/ # ForyStruct macro
│ └── fory_row.rs # ForyRow macro
Use Cases
Object Serialization
- Complex data structures with nested objects and references
- Cross-language communication in microservices
- General-purpose serialization with full type safety
- Schema evolution with compatible mode
- Graph-like data structures with circular references
Row-Based Serialization
- High-throughput data processing
- Analytics workloads requiring fast field access
- Memory-constrained environments
- Real-time data streaming applications
- Zero-copy scenarios
Next Steps
- Configuration - Fory builder options and modes
- Basic Serialization - Object graph serialization
- Xlang Serialization - xlang mode
- Native Serialization - Rust-only serialization
- References - Shared and circular references
- Polymorphism - Trait object serialization
- Custom Serializers - Extend serialization behavior
- Row Format - Zero-copy row-based format