Skip to main content

Fory

Struct Fory 

Source
pub struct Fory { /* private fields */ }
Expand description

The main Fory serialization framework instance.

Fory provides high-performance serialization and deserialization with xlang mode, native mode, reference tracking, and trait object serialization.

§Features

  • Xlang mode: Default wire format for cross-language payloads
  • Native mode: Rust-only wire format selected with .xlang(false)
  • Schema evolution: Compatible and schema-consistent payload choices
  • Reference tracking: Handles shared and circular references
  • Trait object serialization: Supports serializing polymorphic trait objects
  • Dynamic depth limiting: Configurable limit for nested dynamic object serialization

§Examples

Basic usage:

use fory::Fory;
use fory::{ForyEnum, ForyStruct, ForyUnion};

#[derive(ForyStruct)]
struct User {
    name: String,
    age: u32,
}

let mut fory = Fory::builder().xlang(true).build();
fory.register_by_name::<User>("example", "User").unwrap();
let user = User { name: "Alice".to_string(), age: 30 };
let bytes = fory.serialize(&user).unwrap();
let deserialized: User = fory.deserialize(&bytes).unwrap();

Custom configuration:

use fory_core::Fory;

let fory = Fory::builder()
    .xlang(true)
    .compress_string(true)
    .max_dyn_depth(10)
    .build();

Implementations§

Source§

impl Fory

Source

pub fn builder() -> ForyBuilder

Creates a builder for configuring a Fory runtime.

Source

pub fn is_xlang(&self) -> bool

Returns whether xlang mode is enabled.

Source

pub fn is_compatible(&self) -> bool

Returns whether compatible schema evolution is enabled.

§Returns

true if compatible schema evolution is enabled, false otherwise.

Source

pub fn is_compress_string(&self) -> bool

Returns whether string compression is enabled.

§Returns

true if meta string compression is enabled, false otherwise.

Source

pub fn is_check_string_read(&self) -> bool

Returns whether UTF-8 string payload validation is enabled.

Source

pub fn is_share_meta(&self) -> bool

Returns whether metadata sharing is enabled.

§Returns

true if metadata sharing is enabled, false otherwise.

Source

pub fn get_max_dyn_depth(&self) -> u32

Returns the maximum depth for nested dynamic object serialization.

Source

pub fn get_max_binary_size(&self) -> u32

Returns the maximum allowed binary data size in bytes.

Source

pub fn get_max_collection_size(&self) -> u32

Returns the maximum allowed collection/map element count.

Source

pub fn is_check_struct_version(&self) -> bool

Returns whether class version checking is enabled.

§Returns

true if class version checking is enabled, false otherwise.

Source

pub fn config(&self) -> &Config

Returns a reference to the configuration.

Source

pub fn serialize<T>(&self, record: &T) -> Result<Vec<u8>, Error>
where T: Serializer,

Serializes a value of type T into a byte vector.

§Type Parameters
  • T - The type of the value to serialize. Must implement Serializer.
§Arguments
  • record - A reference to the value to serialize.
§Returns

A Vec<u8> containing the serialized data.

§Examples
use fory::Fory;
use fory::{ForyEnum, ForyStruct, ForyUnion};

#[derive(ForyStruct)]
struct Point { x: i32, y: i32 }

let mut fory = Fory::builder().xlang(true).build();
fory.register_by_name::<Point>("example", "Point").unwrap();
let point = Point { x: 10, y: 20 };
let bytes = fory.serialize(&point).unwrap();
Source

pub fn serialize_to<T>( &self, buf: &mut Vec<u8>, record: &T, ) -> Result<usize, Error>
where T: Serializer,

Serializes a value of type T into the provided byte buffer.

The serialized data is appended to the end of the buffer by default. To write from a specific position, resize the buffer before calling this method.

§Type Parameters
  • T - The type of the value to serialize. Must implement Serializer.
§Arguments
  • buf - A mutable reference to the byte buffer to append the serialized data to. The buffer will be resized as needed during serialization.
  • record - A reference to the value to serialize.
§Returns

The number of bytes written to the buffer on success, or an error if serialization fails.

§Notes
  • Multiple serialize_to calls to the same buffer will append data sequentially.
§Examples

Basic usage - appending to a buffer:

use fory_core::Fory;
use fory_derive::{ForyEnum, ForyStruct, ForyUnion};

#[derive(ForyStruct)]
struct Point {
    x: i32,
    y: i32,
}

let mut fory = Fory::builder().xlang(true).build();
fory.register_by_name::<Point>("example", "Point").unwrap();
let point = Point { x: 1, y: 2 };

let mut buf = Vec::new();
let bytes_written = fory.serialize_to(&mut buf, &point).unwrap();
assert_eq!(bytes_written, buf.len());

Multiple serializations to the same buffer:

use fory_core::Fory;
use fory_derive::{ForyEnum, ForyStruct, ForyUnion};

#[derive(ForyStruct, PartialEq, Debug)]
struct Point {
    x: i32,
    y: i32,
}

let mut fory = Fory::builder().xlang(true).build();
fory.register_by_name::<Point>("example", "Point").unwrap();
let p1 = Point { x: 1, y: 2 };
let p2 = Point { x: -3, y: 4 };

let mut buf = Vec::new();

// First serialization
let len1 = fory.serialize_to(&mut buf, &p1).unwrap();
let offset1 = buf.len();

// Second serialization - appends to existing data
let len2 = fory.serialize_to(&mut buf, &p2).unwrap();
let offset2 = buf.len();

assert_eq!(offset1, len1);
assert_eq!(offset2, len1 + len2);

// Deserialize both objects
let deserialized1: Point = fory.deserialize(&buf[0..offset1]).unwrap();
let deserialized2: Point = fory.deserialize(&buf[offset1..offset2]).unwrap();
assert_eq!(deserialized1, p1);
assert_eq!(deserialized2, p2);

Writing to a specific position using resize:

§Notes on vec.resize()

When calling vec.resize(n, 0), note that if n is smaller than the current length, the buffer will be truncated (not shrunk in capacity). The capacity remains unchanged, making subsequent writes efficient for buffer reuse patterns:

use fory_core::Fory;
use fory_derive::{ForyEnum, ForyStruct, ForyUnion};

#[derive(ForyStruct)]
struct Point {
    x: i32,
    y: i32,
}

let mut fory = Fory::builder().xlang(true).build();
fory.register_by_name::<Point>("example", "Point").unwrap();
let point = Point { x: 1, y: 2 };

let mut buf = Vec::with_capacity(1024);
buf.resize(16, 0);  // Set length to 16 to append the write, capacity stays 1024

let initial_capacity = buf.capacity();
fory.serialize_to(&mut buf, &point).unwrap();

// Reset to smaller size to append the write - capacity unchanged
buf.resize(16, 0);
assert_eq!(buf.capacity(), initial_capacity);  // Capacity not shrunk

// Reuse buffer efficiently without reallocation
fory.serialize_to(&mut buf, &point).unwrap();
assert_eq!(buf.capacity(), initial_capacity);  // Still no reallocation
Source

pub fn register<T>(&mut self, id: u32) -> Result<(), Error>
where T: 'static + StructSerializer + Serializer + ForyDefault,

Registers a struct type with a numeric type ID for serialization.

§Type Parameters
  • T - The struct type to register. Must implement StructSerializer, Serializer, and ForyDefault.
§Arguments
  • id - A unique numeric identifier for the type. This ID is used in the serialized format to identify the type during deserialization.
§Panics

May panic if the type ID conflicts with an already registered type.

§Examples
use fory::Fory;
use fory::{ForyEnum, ForyStruct, ForyUnion};

#[derive(ForyStruct)]
struct User { name: String, age: u32 }

let mut fory = Fory::builder().xlang(true).build();
fory.register::<User>(100).unwrap();
Source

pub fn register_union<T>(&mut self, id: u32) -> Result<(), Error>
where T: 'static + StructSerializer + Serializer + ForyDefault,

Register a union type with a numeric type ID.

This is intended for union-compatible enums generated by the compiler.

Source

pub fn register_by_name<T>( &mut self, namespace: &str, type_name: &str, ) -> Result<(), Error>
where T: 'static + StructSerializer + Serializer + ForyDefault,

Registers a struct type with a namespace and type name for xlang serialization.

§Type Parameters
  • T - The struct type to register. Must implement StructSerializer, Serializer, and ForyDefault.
§Arguments
  • namespace - The namespace or package name for the type (e.g., “com.example.types”). Use an empty string for the default namespace.
  • type_name - The name of the type (e.g., “User”).
§Notes

This registration method is preferred for xlang serialization because it uses human-readable type identifiers instead of numeric IDs, which improves compatibility across different language implementations.

§Examples

The example uses xlang mode because name-based registration is the preferred registration style for cross-language payloads.

use fory::Fory;
use fory::{ForyEnum, ForyStruct, ForyUnion};

#[derive(ForyStruct)]
struct User { name: String, age: u32 }

let mut fory = Fory::builder().xlang(true).build();
fory.register_by_name::<User>("com.example", "User").unwrap();
Source

pub fn register_union_by_name<T>( &mut self, namespace: &str, type_name: &str, ) -> Result<(), Error>
where T: 'static + StructSerializer + Serializer + ForyDefault,

Register a union type with namespace and type name.

This is intended for union-compatible enums generated by the compiler.

Source

pub fn register_serializer<T>(&mut self, id: u32) -> Result<(), Error>

Registers a custom serializer type with a numeric type ID.

§Type Parameters
  • T - The type to register. Must implement Serializer and ForyDefault. Unlike register(), this does not require StructSerializer, making it suitable for non-struct types or types with custom serialization logic.
§Arguments
  • id - A unique numeric identifier for the type.
§Use Cases

Use this method to register:

  • Enum types with custom serialization
  • Wrapper types
  • Types with hand-written Serializer implementations
§Examples
use fory_core::Fory;

let mut fory = Fory::builder().xlang(false).build();
fory.register_serializer::<MyCustomType>(200).unwrap();
Source

pub fn register_serializer_by_name<T>( &mut self, namespace: &str, type_name: &str, ) -> Result<(), Error>

Registers a custom serializer type with a namespace and type name.

§Type Parameters
  • T - The type to register. Must implement Serializer and ForyDefault.
§Arguments
  • namespace - The namespace or package name for the type.
  • type_name - The name of the type.
§Notes

This is the named equivalent of register_serializer(), preferred for xlang serialization scenarios.

Source

pub fn register_generic_trait<T>(&mut self) -> Result<(), Error>
where T: 'static + Serializer + ForyDefault,

Registers a generic trait object type for serialization. This method should be used to register collection types such as Vec<T>, HashMap<K, V>, etc. Don’t register concrete struct types with this method. Use register() instead.

Source

pub fn write_head<T>(&self, writer: &mut Writer<'_>)
where T: Serializer,

Writes the serialization header to the writer.

Source

pub fn deserialize<T>(&self, bf: &[u8]) -> Result<T, Error>

Deserializes data from a byte slice into a value of type T.

§Type Parameters
  • T - The target type to deserialize into. Must implement Serializer and ForyDefault.
§Arguments
  • bf - The byte slice containing the serialized data.
§Returns
  • Ok(T) - The deserialized value on success.
  • Err(Error) - An error if deserialization fails (e.g., invalid format, type mismatch).
§Panics

Panics in debug mode if there are unread bytes remaining after successful deserialization, indicating a potential protocol violation.

§Examples
use fory::Fory;
use fory::{ForyEnum, ForyStruct, ForyUnion};

#[derive(ForyStruct)]
struct Point { x: i32, y: i32 }

let mut fory = Fory::builder().xlang(true).build();
fory.register_by_name::<Point>("example", "Point").unwrap();
let point = Point { x: 10, y: 20 };
let bytes = fory.serialize(&point).unwrap();
let deserialized: Point = fory.deserialize(&bytes).unwrap();
Source

pub fn deserialize_from<T>(&self, reader: &mut Reader<'_>) -> Result<T, Error>

Deserializes data from a Reader into a value of type T.

This method is the paired read operation for serialize_to. It reads serialized data from the current position of the reader and automatically advances the cursor to the end of the read data, making it suitable for reading multiple objects sequentially from the same buffer.

§Type Parameters
  • T - The target type to deserialize into. Must implement Serializer and ForyDefault.
§Arguments
  • reader - A mutable reference to the Reader containing the serialized data. The reader’s cursor will be advanced to the end of the deserialized data.
§Returns
  • Ok(T) - The deserialized value on success.
  • Err(Error) - An error if deserialization fails (e.g., invalid format, type mismatch).
§Notes
  • The reader’s cursor is automatically updated after each successful read.
  • This method is ideal for reading multiple objects from the same buffer sequentially.
  • See serialize_to for complete usage examples.
§Examples

Basic usage:

use fory_core::{Fory, Reader};
use fory_derive::{ForyEnum, ForyStruct, ForyUnion};

#[derive(ForyStruct)]
struct Point { x: i32, y: i32 }

let mut fory = Fory::builder().xlang(true).build();
fory.register_by_name::<Point>("example", "Point").unwrap();
let point = Point { x: 10, y: 20 };

let mut buf = Vec::new();
fory.serialize_to(&mut buf, &point).unwrap();

let mut reader = Reader::new(&buf);
let deserialized: Point = fory.deserialize_from(&mut reader).unwrap();

Trait Implementations§

Source§

impl Default for Fory

Source§

fn default() -> Fory

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl !Freeze for Fory

§

impl RefUnwindSafe for Fory

§

impl Send for Fory

§

impl Sync for Fory

§

impl Unpin for Fory

§

impl UnsafeUnpin for Fory

§

impl UnwindSafe for Fory

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.