Skip to main content
Version: dev

Type Registration

This page covers type registration methods in Apache Fory™ Rust.

Register by ID

Register types with a numeric ID for fast, compact serialization:

use fory::Fory;
use fory::ForyStruct;

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

let mut fory = Fory::builder().xlang(false).build();
fory.register::<User>(1)?;

let user = User {
name: "Alice".to_string(),
age: 30,
};

let bytes = fory.serialize(&user)?;
let decoded: User = fory.deserialize(&bytes)?;

Register by Name

For cross-language compatibility, register with a stable name. Use . to separate a namespace prefix from the type name:

let mut fory = Fory::builder().xlang(true).build();

// Register with symbolic type identity
fory.register_by_name::<MyStruct>("com.example.MyStruct")?;

Register a Custom Serializer

For types that need custom serialization logic, register the custom serializer:

let mut fory = Fory::builder().xlang(false).build();
fory.register_serializer::<UuidSerializer>(100)?;

An external structural serializer uses the ordinary structural registration API:

fory.register::<UserSerializer>(101)?;

The serializer's Target is the runtime value type. Registration does not require a separate external-type API. At fields, with can select an exact carrier serializer such as VecSerializer<UserSerializer>, while recursive list, map, or tuple annotations select serializers at child nodes. At roots, compose the same carrier serializers. Carrier serializers are not registered.

Registration Consistency

Rust registration APIs use explicit IDs or explicit names. Keep the same registration mapping on serializer and deserializer peers:

// Serializer side
let mut fory = Fory::builder().xlang(false).build();
fory.register::<TypeA>(1)?;
fory.register::<TypeB>(2)?;
fory.register::<TypeC>(3)?;

// Deserializer side - MUST use the same ID mapping
let mut fory = Fory::builder().xlang(false).build();
fory.register::<TypeA>(1)?;
fory.register::<TypeB>(2)?;
fory.register::<TypeC>(3)?;

Thread-Safe Registration

Perform all registrations before spawning threads:

use std::sync::Arc;
use std::thread;

let mut fory = Fory::builder().xlang(false).build();
fory.register::<User>(1)?;
fory.register::<Order>(2)?;

// Now share across threads
let fory = Arc::new(fory);

let handles: Vec<_> = (0..4)
.map(|_| {
let shared = Arc::clone(&fory);
thread::spawn(move || {
// Use fory for serialization
})
})
.collect();

Best Practices

  1. Use consistent IDs: Same type ID across all languages for cross-language compatibility
  2. Register before threading: Complete all registrations before spawning threads
  3. Use namespace for xlang: Makes type names consistent across languages
  4. Explicit IDs for stability: Avoid auto-generated IDs in production