| --- |
| title: Rust Object Serialization |
| sidebar_position: 0 |
| id: index |
| license: | |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --- |
| |
| **Apache Fory™** is a high-performance multi-language serialization framework. The Rust implementation uses compile-time code generation for object serialization. |
| |
| 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, Rust, JavaScript/TypeScript, C#, Swift, Dart, Scala, and Kotlin |
| - **Type-safe**: Compile-time type checking with derive macros |
| - **Circular references**: Automatic tracking of shared and circular references with `Rc`/`Arc` and weak pointers |
| - **Polymorphic**: Serialize trait objects with `Box<dyn Trait>`, `Rc<dyn Trait>`, and `Arc<dyn Trait>` |
| - **Schema evolution**: Compatible mode for independent schema changes |
| |
| ## Crates |
| |
| | Crate | Description | Version | |
| | --------------------------------------------------------------------------- | ----------------------------------------------------- | --------------------------------------------- | |
| | [`fory`](https://github.com/apache/fory/blob/main/rust/fory) | User-facing API, public Fory types, and derive macros | [1.6.1](https://crates.io/crates/fory) | |
| | [`fory-core`](https://github.com/apache/fory/blob/main/rust/fory-core/) | Lower-level core crate for advanced integrations | [1.6.1](https://crates.io/crates/fory-core) | |
| | [`fory-derive`](https://github.com/apache/fory/blob/main/rust/fory-derive/) | Procedural macro crate for direct derive-macro use | [1.6.1](https://crates.io/crates/fory-derive) | |
| |
| Most applications should depend on `fory` only. It re-exports the derive |
| macros and the public Fory types needed by generated code. Use `fory-core` |
| or `fory-derive` directly only when intentionally building on the lower-level |
| crates. |
| |
| ## Quick Start |
| |
| Add Apache Fory™ to your `Cargo.toml`: |
| |
| ```toml |
| [dependencies] |
| fory = "1.6.1" |
| ``` |
| |
| ### Basic Example |
| |
| ```rust |
| 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 implementations. 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)` and keeps Rust object serialization in Rust-native form. It supports native-only concrete targets and data-enum shapes that have no xlang representation. Dynamic `Any`, application trait, and shared-reference carriers can also be used in xlang mode when every selected concrete target is xlang-compatible. Compatible mode is enabled by default. Set `.compatible(false)` only when every reader and writer uses the same Rust schema and you want faster serialization and smaller size. |
| |
| See [Cross-Language Interoperability](basic-serialization.md#cross-language-interoperability) for Rust xlang registration and interoperability rules, and [Native Serialization](native.md) 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. |
| |
| ```rust |
| 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. |
| |
| ## 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 |
| |
| ## Next Steps |
| |
| - [Configuration](configuration.md) - Fory builder options and modes |
| - [Basic Serialization](basic-serialization.md) - Default xlang object graphs and interoperability |
| - [Native Serialization](native.md) - Rust-only serialization |
| - [References](references.md) - Shared and circular references |
| - [Polymorphism](polymorphism.md) - Trait object serialization |
| - [Custom Serializers](custom-serializers.md) - Implement custom serialization behavior |
| - [External-Type Serialization](external-types.md) - External structural and custom serializers |
| plus carrier composition |
| - [Row Format](../../row-format/rust.md) - Standard Row Format with borrowed views |
| - [gRPC Support](../../grpc/rust.md) - Fory payloads over tonic |
| |
| Before decoding bytes from outside the application trust boundary, read |
| [Rust Security](security.md). |