blob: f150a5c98543a8de7bf8d431ae786796479ffd9a [file] [view]
---
title: Rust
sidebar_position: 4
id: rust
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.
---
## Output Layout
Rust output is one module file per schema, for example:
- `<rust_out>/addressbook.rs`
When `--grpc` is used and the schema contains services, Rust also emits:
- `<rust_out>/addressbook_service.rs`
- `<rust_out>/addressbook_service_grpc.rs`
## Type Generation
Unions map to Rust enums with `#[fory(id = ...)]` schema case attributes.
`#[fory(unknown)] Unknown(::fory::UnknownCase)` marks the Fory-provided
forward-compatibility carrier. The marker only selects the carrier and does not
add an entry to the schema case table; schema cases still use the full `0..N`
ID range. A generated typed union must have at least one non-`Unknown` case. The
compiler marks the first declared non-`Unknown` case as `#[fory(default)]`.
When that case's payload implements Rust's standard `Default` trait, the
compiler also emits a standard `Default` implementation from that case:
```rust
#[derive(::fory::ForyUnion, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Animal {
#[fory(unknown)]
Unknown(::fory::UnknownCase),
#[fory(id = 0, default)]
Dog(self::Dog),
#[fory(id = 1)]
Cat(self::Cat),
}
impl ::std::default::Default for Animal {
fn default() -> Self {
Self::Dog(<self::Dog as ::std::default::Default>::default())
}
}
```
If the selected payload does not implement standard `Default`, such as an
`any` payload, the generated union has no infallible `Default`
implementation. This model-level default is independent of Fory's fallible
deserialization default, which reconstructs the selected case through its
codecs and active read context.
Nested types generate nested modules:
```rust
pub mod person {
#[derive(ForyEnum, Debug, Clone, PartialEq, Default)]
#[repr(i32)]
pub enum PhoneType {
#[default]
Mobile = 0,
Home = 1,
Work = 2,
}
#[derive(ForyStruct, Debug, Clone, PartialEq, Default)]
pub struct PhoneNumber {
#[fory(id = 1)]
pub number: String,
#[fory(id = 2)]
pub phone_type: PhoneType,
}
}
```
Messages derive `ForyStruct` and include `to_bytes`/`from_bytes` helpers:
```rust
#[derive(ForyStruct, Debug, Clone, PartialEq, Default)]
pub struct Person {
#[fory(id = 1)]
pub name: String,
#[fory(id = 7)]
pub phones: Vec<person::PhoneNumber>,
#[fory(id = 8)]
pub pet: Animal,
}
```
## Registration
Generated registration function:
```rust
pub fn register_types(fory: &mut Fory) -> Result<(), fory::Error> {
fory.register_union::<Animal>(106)?;
fory.register::<person::PhoneType>(101)?;
fory.register::<person::PhoneNumber>(102)?;
fory.register::<Person>(100)?;
fory.register::<Dog>(104)?;
fory.register::<Cat>(105)?;
fory.register::<AddressBook>(103)?;
Ok(())
}
```
For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs:
```rust
fory.register::<Status>(1124725126)?;
fory.register_union::<Wrapper>(1471345060)?;
fory.register::<Envelope>(3022445236)?;
fory.register_union::<envelope::Detail>(1609214087)?;
fory.register::<envelope::Payload>(2862577837)?;
```
If `option enable_auto_type_id = false;` is set:
```rust
fory.register_by_name::<Config>("myapp.models.Config")?;
fory.register_union_by_name::<Holder>("myapp.models.Holder")?;
```
## Usage
```rust
let person = Person {
name: "Alice".into(),
pet: Animal::Dog(self::Dog::default()),
..Default::default()
};
let bytes = person.to_bytes()?;
let restored = Person::from_bytes(&bytes)?;
```
## gRPC Service Companions
With `--grpc`, Rust emits `<module>_service.rs` for the async service trait and path constants, and `<module>_service_grpc.rs` for tonic clients, servers, codecs, and `ForyGrpcPayload` implementations backed by the model's `to_bytes` and `from_bytes` helpers. See [Rust gRPC](../../grpc/rust.md) for dependencies and usage.