---
title: Generated Code
sidebar_position: 5
id: generated_code
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.
---

This document explains generated code for each target language.

Fory IDL generated types are idiomatic in host languages and can be used directly as domain objects. Generated types also include `to/from bytes` helpers and schema modules or registration helpers, depending on the target language.

Generated schema modules are named from the schema source file, not from the
package or namespace. In targets that expose the module directly in a language
package or namespace, names such as `AddressbookForyModule` or
`ComplexPbForyModule` let multiple IDL files target the same package or
namespace without producing colliding `ForyModule` types.

## Reference Schemas

The examples below use two real schemas:

1. `addressbook.fdl` (explicit type IDs)
2. `auto_id.fdl` (no explicit type IDs)

### `addressbook.fdl` (excerpt)

```protobuf
package addressbook;

option go_package = "github.com/myorg/myrepo/gen/addressbook;addressbook";

message Person [id=100] {
    string name = 1;
    int32 id = 2;

    enum PhoneType [id=101] {
        PHONE_TYPE_MOBILE = 0;
        PHONE_TYPE_HOME = 1;
        PHONE_TYPE_WORK = 2;
    }

    message PhoneNumber [id=102] {
        string number = 1;
        PhoneType phone_type = 2;
    }

    list<PhoneNumber> phones = 7;
    Animal pet = 8;
}

message Dog [id=104] {
    string name = 1;
    int32 bark_volume = 2;
}

message Cat [id=105] {
    string name = 1;
    int32 lives = 2;
}

union Animal [id=106] {
    Dog dog = 1;
    Cat cat = 2;
}

message AddressBook [id=103] {
    list<Person> people = 1;
    map<string, Person> people_by_name = 2;
}
```

### `auto_id.fdl` (excerpt)

```protobuf
package auto_id;

enum Status {
    UNKNOWN = 0;
    OK = 1;
}

message Envelope {
    string id = 1;

    message Payload {
        int32 value = 1;
    }

    union Detail {
        Payload payload = 1;
        string note = 2;
    }

    Payload payload = 2;
    Detail detail = 3;
    Status status = 4;
}

union Wrapper {
    Envelope envelope = 1;
    string raw = 2;
}
```

## Java

### Output Layout

For `package addressbook`, Java output is generated under:

- `<java_out>/addressbook/`
- Type files: `AddressBook.java`, `Person.java`, `Dog.java`, `Cat.java`, `Animal.java`
- Schema module: `AddressbookForyModule.java`

For schemas without a Java package, the schema module name is derived from the
source file stem, for example `main.fdl` generates `MainForyModule.java`.
Java import graphs cannot mix default-package schemas with named Java packages.

### Type Generation

Messages generate Java classes with `@ForyField`, default constructors, getters/setters, and byte helpers:

```java
public class Person {
    public static enum PhoneType {
        MOBILE,
        HOME,
        WORK;
    }

    public static class PhoneNumber {
        @ForyField(id = 1)
        private String number;

        @ForyField(id = 2)
        private PhoneType phoneType;

        public byte[] toBytes() { ... }
        public static PhoneNumber fromBytes(byte[] bytes) { ... }
    }

    @ForyField(id = 1)
    private String name;

    @ForyField(id = 8)
    private Animal pet;

    public byte[] toBytes() { ... }
    public static Person fromBytes(byte[] bytes) { ... }
}
```

Messages with `evolving=false` are generated with Java fixed-schema struct encoding.

Unions generate classes extending `org.apache.fory.type.union.Union`:

```java
public final class Animal extends Union {
    public enum AnimalCase {
        DOG(1),
        CAT(2);
        public final int id;
        AnimalCase(int id) { this.id = id; }
    }

    public static Animal ofDog(Dog v) { ... }
    public AnimalCase getAnimalCase() { ... }
    public int getAnimalCaseId() { ... }

    public boolean hasDog() { ... }
    public Dog getDog() { ... }
    public void setDog(Dog v) { ... }
}
```

### Schema Module

Each JVM schema generates a `ForyModule`. Imported schema modules are installed
through `fory.register(...)`, so shared imports are deduplicated by the Fory instance.

```java
public final class AddressbookForyModule implements org.apache.fory.ForyModule {
  public static final AddressbookForyModule INSTANCE = new AddressbookForyModule();

  static ThreadSafeFory getFory() { ... }

  @Override
  public void install(Fory fory) {
    org.apache.fory.resolver.TypeResolver resolver = fory.getTypeResolver();
    resolver.registerUnion(Animal.class, 106L, new org.apache.fory.serializer.UnionSerializer(resolver, Animal.class));
    resolver.register(Person.class, 100L);
    resolver.register(Person.PhoneType.class, 101L);
    resolver.register(Person.PhoneNumber.class, 102L);
    resolver.register(Dog.class, 104L);
    resolver.register(Cat.class, 105L);
    resolver.register(AddressBook.class, 103L);
  }
}
```

For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs (for example from `auto_id.fdl`):

```java
resolver.register(Status.class, 1124725126L);
resolver.registerUnion(Wrapper.class, 1471345060L, new org.apache.fory.serializer.UnionSerializer(resolver, Wrapper.class));
resolver.register(Envelope.class, 3022445236L);
resolver.registerUnion(Envelope.Detail.class, 1609214087L, new org.apache.fory.serializer.UnionSerializer(resolver, Envelope.Detail.class));
resolver.register(Envelope.Payload.class, 2862577837L);
```

If `option enable_auto_type_id = false;` is set, registration uses symbolic names:

```java
resolver.register(Config.class, "myapp.models", "Config");
resolver.registerUnion(
    Holder.class,
    "myapp.models",
    "Holder",
    new org.apache.fory.serializer.UnionSerializer(resolver, Holder.class));
```

### Usage

```java
Person person = new Person();
person.setName("Alice");
person.setPet(Animal.ofDog(new Dog()));

byte[] data = person.toBytes();
Person restored = Person.fromBytes(data);
```

### gRPC Service Companions

When a schema contains services and the compiler is run with `--grpc`, Java
generation emits one `<ServiceName>Grpc.java` file per service next to the model
types.

```java
public final class AddressBookServiceGrpc {
  public static final String SERVICE_NAME = "addressbook.AddressBookService";

  public static AddressBookServiceStub newStub(io.grpc.Channel channel) { ... }
  public static AddressBookServiceBlockingStub newBlockingStub(io.grpc.Channel channel) { ... }
  public static AddressBookServiceFutureStub newFutureStub(io.grpc.Channel channel) { ... }

  public abstract static class AddressBookServiceImplBase
      implements io.grpc.BindableService {
    public void lookup(Person request, io.grpc.stub.StreamObserver<AddressBook> responseObserver) { ... }
  }
}
```

The generated marshaller serializes each request or response with the schema
module's `ThreadSafeFory`. It uses grpc-java's `MethodDescriptor.Marshaller`
API, so applications compiling these files must provide grpc-java dependencies.
Those dependencies are not added to Fory Java artifacts.

## Python

### Output Layout

Python output is one module per schema file, for example:

- `<python_out>/addressbook.py`

### Type Generation

Unions generate a case enum plus a `Union` subclass with typed helpers:

```python
class AnimalCase(Enum):
    DOG = 1
    CAT = 2

class Animal(Union):
    @classmethod
    def dog(cls, v: Dog) -> "Animal": ...

    def case(self) -> AnimalCase: ...
    def case_id(self) -> int: ...

    def is_dog(self) -> bool: ...
    def dog_value(self) -> Dog: ...
    def set_dog(self, v: Dog) -> None: ...
```

Messages generate `@pyfory.dataclass` types, and nested types stay nested:

```python
@pyfory.dataclass
class Person:
    class PhoneType(IntEnum):
        MOBILE = 0
        HOME = 1
        WORK = 2

    @pyfory.dataclass
    class PhoneNumber:
        number: str = pyfory.field(id=1, default="")
        phone_type: Person.PhoneType = pyfory.field(id=2, default=None)

    name: str = pyfory.field(id=1, default="")
    phones: List[Person.PhoneNumber] = pyfory.field(id=7, default_factory=list)
    pet: Animal = pyfory.field(id=8, default=None)

    def to_bytes(self) -> bytes: ...
    @classmethod
    def from_bytes(cls, data: bytes) -> "Person": ...
```

### Registration

Generated registration function:

```python
def register_addressbook_types(fory: pyfory.Fory):
    fory.register_union(Animal, type_id=106, serializer=AnimalSerializer(fory))
    fory.register_type(Person, type_id=100)
    fory.register_type(Person.PhoneType, type_id=101)
    fory.register_type(Person.PhoneNumber, type_id=102)
    fory.register_type(Dog, type_id=104)
    fory.register_type(Cat, type_id=105)
    fory.register_type(AddressBook, type_id=103)
```

For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs:

```python
fory.register_type(Status, type_id=1124725126)
fory.register_union(Wrapper, type_id=1471345060, serializer=WrapperSerializer(fory))
fory.register_type(Envelope, type_id=3022445236)
fory.register_union(Envelope.Detail, type_id=1609214087, serializer=Envelope.DetailSerializer(fory))
fory.register_type(Envelope.Payload, type_id=2862577837)
```

If `option enable_auto_type_id = false;` is set:

```python
fory.register_type(Config, name="myapp.models.Config")
fory.register_union(
    Holder,
    name="myapp.models.Holder",
    serializer=HolderSerializer(fory),
)
```

### Usage

```python
person = Person(name="Alice", pet=Animal.dog(Dog(name="Rex", bark_volume=10)))

data = person.to_bytes()
restored = Person.from_bytes(data)
```

### gRPC Service Companions

When a schema contains services and the compiler is run with `--grpc`, Python
generation emits a companion module named `<module>_grpc.py`. The module name is
derived from the Fory package by replacing dots with underscores, or `generated`
when the schema has no package. Python gRPC output defaults to `grpc.aio`
AsyncIO APIs.

```python
import grpc
import grpc.aio


class AddressBookServiceStub:
    def __init__(self, channel):
        self.lookup = channel.unary_unary(
            "/addressbook.AddressBookService/Lookup",
            request_serializer=_serialize,
            response_deserializer=_deserialize,
        )


class AddressBookServiceServicer:
    async def lookup(self, request, context):
        await context.abort(grpc.StatusCode.UNIMPLEMENTED, "Method not implemented!")


def add_servicer(servicer, server): ...
```

Python gRPC serializers receive and return complete `bytes` payloads, so the
generated callbacks call the model module's `_get_fory().serialize(...)` and
`_get_fory().deserialize(...)` directly. Applications using the generated
companion module must install `grpcio`; `pyfory` does not add a hard gRPC
dependency. The Python API uses snake_case method names while preserving the
original IDL method names in the gRPC wire paths.

Generate synchronous Python `grpcio` companions with
`--grpc --grpc-python-mode=sync`. Sync mode keeps the same generated filename
and public names, but servicer methods use regular `def` methods and sync
`grpc.Channel` and `grpc.Server` instances.

## Rust

### 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)]` and
emits `Default` 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 ::fory::ForyDefault>::fory_default())
    }
}
```

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

When a schema contains services and the compiler is run with `--grpc`, Rust
generation emits a service API module and a tonic binding module. For a schema
module named `addressbook`, those files are `addressbook_service.rs` and
`addressbook_service_grpc.rs`.

The service API module contains the async trait and gRPC path constants:

```rust
#[::tonic::async_trait]
pub trait AddressBookService: ::std::marker::Send + ::std::marker::Sync + 'static {
    async fn lookup(
        &self,
        request: ::tonic::Request<crate::addressbook::Person>,
    ) -> ::std::result::Result<
        ::tonic::Response<crate::addressbook::AddressBook>,
        ::tonic::Status,
    >;
}

pub const ADDRESS_BOOK_SERVICE_SERVICE_NAME: &str = "addressbook.AddressBookService";
pub const ADDRESS_BOOK_SERVICE_LOOKUP_PATH: &str = "/addressbook.AddressBookService/Lookup";
```

The tonic binding module contains Fory-backed codecs, payload implementations,
and client/server wrappers. It serializes each request or response with the
generated model type's `to_bytes` and `from_bytes` helpers:

```rust
impl codec::ForyGrpcPayload for crate::addressbook::Person {
    fn encode_fory_payload(&self) -> ::std::result::Result<::std::vec::Vec<u8>, ::fory::Error> {
        self.to_bytes()
    }

    fn decode_fory_payload(payload: &[u8]) -> ::std::result::Result<Self, ::fory::Error> {
        Self::from_bytes(payload)
    }
}
```

Applications compiling the generated Rust service files must provide `tonic` and
`bytes` dependencies; Fory's Rust crate does not add those gRPC dependencies as
hard dependencies.

## C++

### Output Layout

C++ output is one header per schema file, for example:

- `<cpp_out>/addressbook.h`

### Type Generation

Messages generate `final` classes with typed accessors and byte helpers:

```cpp
class Person final {
 public:
  class PhoneNumber final {
   public:
    const std::string& number() const;
    std::string* mutable_number();
    template <class Arg, class... Args>
    void set_number(Arg&& arg, Args&&... args);

    fory::Result<std::vector<uint8_t>, fory::Error> to_bytes() const;
    static fory::Result<PhoneNumber, fory::Error> from_bytes(const std::vector<uint8_t>& data);
  };

  const std::string& name() const;
  std::string* mutable_name();
  template <class Arg, class... Args>
  void set_name(Arg&& arg, Args&&... args);

  const Animal& pet() const;
  Animal* mutable_pet();
};
```

Optional message fields generate `has_xxx`, `mutable_xxx`, and `clear_xxx` APIs:

```cpp
class Envelope final {
 public:
  bool has_payload() const { return payload_ != nullptr; }
  const Envelope::Payload& payload() const { return *payload_; }
  Envelope::Payload* mutable_payload() {
    if (!payload_) {
      payload_ = std::make_unique<Envelope::Payload>();
    }
    return payload_.get();
  }
  void clear_payload() { payload_.reset(); }

 private:
  std::unique_ptr<Envelope::Payload> payload_;
};
```

Unions generate `std::variant` wrappers:

```cpp
class Animal final {
 public:
  enum class AnimalCase : uint32_t {
    DOG = 1,
    CAT = 2,
  };

  static Animal dog(Dog v);
  static Animal cat(Cat v);

  AnimalCase animal_case() const noexcept;
  uint32_t animal_case_id() const noexcept;

  bool is_dog() const noexcept;
  const Dog* as_dog() const noexcept;
  Dog* as_dog() noexcept;
  const Dog& dog() const;
  Dog& dog();

  template <class Visitor>
  decltype(auto) visit(Visitor&& vis) const;

 private:
  std::variant<Dog, Cat> value_;
};
```

Generated headers include `FORY_UNION`, `FORY_ENUM`, and `FORY_STRUCT` macros
for serialization metadata. Field and payload configuration is embedded in the
generated `FORY_STRUCT`/`FORY_UNION` entries.

### Registration

Generated registration function:

```cpp
inline void register_types(fory::serialization::BaseFory& fory) {
    fory.register_union<Animal>(106);
    fory.register_enum<Person::PhoneType>(101);
    fory.register_struct<Person::PhoneNumber>(102);
    fory.register_struct<Person>(100);
    fory.register_struct<Dog>(104);
    fory.register_struct<Cat>(105);
    fory.register_struct<AddressBook>(103);
}
```

For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs:

```cpp
fory.register_enum<Status>(1124725126);
fory.register_union<Wrapper>(1471345060);
fory.register_struct<Envelope>(3022445236);
fory.register_union<Envelope::Detail>(1609214087);
fory.register_struct<Envelope::Payload>(2862577837);
```

If `option enable_auto_type_id = false;` is set:

```cpp
fory.register_struct<Config>("myapp.models.Config");
fory.register_union<Holder>("myapp.models.Holder");
```

### Usage

```cpp
addressbook::Person person;
person.set_name("Alice");
*person.mutable_pet() = addressbook::Animal::dog(addressbook::Dog{});

auto bytes = person.to_bytes();
auto restored = addressbook::Person::from_bytes(bytes.value());
```

## Go

### Output Layout

Go output path depends on schema options and `--go_out`.

For `addressbook.fdl`, `go_package` is configured and generated output follows the configured import path/package (for example under your `--go_out` root).

Without `go_package`, output uses the requested `--go_out` directory and package-derived file naming.

### Type Generation

Nested types use underscore naming by default (`Person_PhoneType`, `Person_PhoneNumber`):

```go
type Person_PhoneType int32

const (
    Person_PhoneTypeMobile Person_PhoneType = 0
    Person_PhoneTypeHome   Person_PhoneType = 1
    Person_PhoneTypeWork   Person_PhoneType = 2
)

type Person_PhoneNumber struct {
    Number    string           `fory:"id=1"`
    PhoneType Person_PhoneType `fory:"id=2"`
}
```

Messages generate structs with `fory` tags and byte helpers:

```go
type Person struct {
    Name   string               `fory:"id=1"`
    Id     int32                `fory:"id=2"`
    Phones []Person_PhoneNumber `fory:"id=7,type=list"`
    Pet    Animal               `fory:"id=8"`
}

func (m *Person) ToBytes() ([]byte, error) { ... }
func (m *Person) FromBytes(data []byte) error { ... }
```

Unions generate typed case structs with constructors/accessors/visitor APIs:

```go
type AnimalCase uint32

type Animal struct {
    case_ AnimalCase
    value any
}

func DogAnimal(v *Dog) Animal { ... }
func CatAnimal(v *Cat) Animal { ... }

func (u Animal) Case() AnimalCase { ... }
func (u Animal) AsDog() (*Dog, bool) { ... }
func (u Animal) Visit(visitor AnimalVisitor) error { ... }
```

### Registration

Generated registration function:

```go
func RegisterTypes(f *fory.Fory) error {
    if err := f.RegisterUnion(Animal{}, 106, fory.NewUnionSerializer(...)); err != nil {
        return err
    }
    if err := f.RegisterEnum(Person_PhoneType(0), 101); err != nil {
        return err
    }
    if err := f.RegisterStruct(Person_PhoneNumber{}, 102); err != nil {
        return err
    }
    if err := f.RegisterStruct(Person{}, 100); err != nil {
        return err
    }
    return nil
}
```

For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs:

```go
if err := f.RegisterEnum(Status(0), 1124725126); err != nil { ... }
if err := f.RegisterUnion(Wrapper{}, 1471345060, fory.NewUnionSerializer(...)); err != nil { ... }
if err := f.RegisterStruct(Envelope{}, 3022445236); err != nil { ... }
if err := f.RegisterUnion(Envelope_Detail{}, 1609214087, fory.NewUnionSerializer(...)); err != nil { ... }
if err := f.RegisterStruct(Envelope_Payload{}, 2862577837); err != nil { ... }
```

If `option enable_auto_type_id = false;` is set:

```go
if err := f.RegisterStructByName(Config{}, "myapp.models.Config"); err != nil { ... }
if err := f.RegisterUnionByName(Holder{}, "myapp.models.Holder", fory.NewUnionSerializer(...)); err != nil { ... }
```

`go_nested_type_style` controls nested type naming:

```protobuf
option go_nested_type_style = "camelcase";
```

The CLI flag `--go_nested_type_style` overrides this schema option when both are set.

### Usage

```go
person := &Person{
    Name: "Alice",
    Pet:  DogAnimal(&Dog{Name: "Rex"}),
}

data, err := person.ToBytes()
if err != nil {
    panic(err)
}
var restored Person
if err := restored.FromBytes(data); err != nil {
    panic(err)
}
```

### gRPC Service Companions

When a schema contains services and the compiler is run with `--grpc`, Go
generation emits one `<module>_grpc.go` file next to the model file. The
companion contains grpc-go client and server interfaces plus a Fory-backed
`CodecV2`.

```go
type AddressBookServiceClient interface {
    Lookup(ctx context.Context, in *Person, opts ...grpc.CallOption) (*AddressBook, error)
}

func NewAddressBookServiceClient(cc grpc.ClientConnInterface) AddressBookServiceClient { ... }

type CodecV2 struct{}
```

The generated codec uses the same package-level thread-safe Fory runtime as the
generated `ToBytes` and `FromBytes` helpers. Applications should pass
`CodecV2{}` to grpc-go server options, and generated clients force the same
codec on each call:

```go
server := grpc.NewServer(grpc.ForceServerCodecV2(addressbook.CodecV2{}))
addressbook.RegisterAddressBookServiceServer(server, service)

client := addressbook.NewAddressBookServiceClient(conn)
```

Go method names are exported as PascalCase identifiers, while the gRPC method
path keeps the exact service and method names from the schema. Regenerate both
peers after changing service or method names.

Applications compiling these files must provide grpc-go dependencies; Fory Go
packages do not add gRPC as a hard dependency.

## C\#

### Output Layout

C# output is one `.cs` file per schema, for example:

- `<csharp_out>/addressbook/Addressbook.cs`

The C# model file name uses the normalized PascalCase source file stem. For
example, `service.fdl` generates `Service.cs`, `order-events.fdl` generates
`OrderEvents.cs`, and `123-schema.fdl` generates `Schema123Schema.cs`.

### Type Generation

Messages generate `[ForyStruct]` classes with C# properties and byte helpers:

```csharp
[ForyStruct]
public sealed partial class Person
{
    public string Name { get; set; } = string.Empty;
    public int Id { get; set; }
    public List<Person.PhoneNumber> Phones { get; set; } = new();
    public Animal Pet { get; set; } = null!;

    public byte[] ToBytes() { ... }
    public static Person FromBytes(byte[] data) { ... }
}
```

Unions generate `[ForyUnion]` ADTs. `Unknown(UnknownCase)` is the
Fory-provided forward-compatibility carrier marked with `[ForyUnknownCase]`.
The marker only selects the carrier and does not add an entry to the schema case
table. Schema-defined cases use non-negative `[ForyCase]` IDs. If a case needs
non-default schema encoding, the generated `[ForyCase]` carries `Type`. Known
case record names are PascalCase FDL case names; payload types are emitted as
qualified references when needed to avoid name conflicts. A typed union must
have at least one non-`Unknown` case.

```csharp
[ForyUnion]
public abstract partial record Animal
{
    private Animal() {}

    [ForyUnknownCase]
    public sealed partial record Unknown(UnknownCase Value) : Animal;

    [ForyCase(0)]
    public sealed partial record Dog(global::addressbook.Dog Value) : Animal;

    [ForyCase(1)]
    public sealed partial record Cat(global::addressbook.Cat Value) : Animal;
}
```

### Module Installation

Each schema generates a module class that installs imported modules first and
then registers the local schema types:

```csharp
public static class AddressbookForyModule
{
    public static void Install(Fory fory)
    {
        fory.Register<addressbook.Animal>((uint)106);
        fory.Register<addressbook.Person>((uint)100);
        // ...
    }
}
```

The C# model file basename and module class both use the normalized source file
stem. They do not use `csharp_namespace` and they do not use gRPC service names.
For example, `service.fdl` generates `Service.cs` and `ServiceForyModule`,
while `order-events.fdl` generates `OrderEvents.cs` and
`OrderEventsForyModule`. A gRPC service named `Greeter` generates the service
companion `GreeterGrpc.cs`; it does not change the schema module name. To get
`GreeterForyModule`, name the schema file `greeter.fdl` or `Greeter.fdl`.

This source-file rule lets several schemas target the same C# namespace without
colliding. No namespace-derived or service-derived module alias is generated.

When explicit type IDs are not provided, generated installation uses computed
numeric IDs (same behavior as other targets).

### gRPC Service Companions

When a schema contains services and the compiler is run with `--grpc`, C#
generation emits one `<ServiceName>Grpc.cs` file per service next to the schema
model file.

```csharp
public static partial class AddressBookService
{
    public abstract partial class AddressBookServiceBase
    {
        public virtual Task<AddressBook> Lookup(
            Person request,
            grpc::ServerCallContext context) { ... }
    }

    public partial class AddressBookServiceClient
        : grpc::ClientBase<AddressBookServiceClient>
    {
        public virtual AddressBook Lookup(Person request, grpc::CallOptions options) { ... }
        public virtual grpc::AsyncUnaryCall<AddressBook> LookupAsync(
            Person request,
            grpc::CallOptions options) { ... }
    }

    public static grpc::ServerServiceDefinition BindService(
        AddressBookServiceBase serviceImpl) { ... }

    public static void BindService(
        grpc::ServiceBinderBase serviceBinder,
        AddressBookServiceBase? serviceImpl) { ... }
}
```

Each generated method descriptor uses a static Fory-backed
`Grpc.Core.Marshaller<T>` that reuses the schema module's `ThreadSafeFory`.
Deserialization reads the gRPC body through `PayloadAsReadOnlySequence()` and
rejects trailing bytes after the single Fory frame. Generated service companions
do not use protobuf parsers and do not create Fory instances per RPC call.

Streaming RPCs map to standard gRPC C# APIs:

| IDL shape                                 | Server method                                                                 | Client method                               |
| ----------------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------- |
| `rpc A (Req) returns (Res)`               | `Task<Res> A(Req request, ServerCallContext context)`                         | `A(...)` and `AAsync(...)`                  |
| `rpc A (Req) returns (stream Res)`        | `Task A(Req request, IServerStreamWriter<Res> responseStream, ...)`           | `AsyncServerStreamingCall<Res> A(...)`      |
| `rpc A (stream Req) returns (Res)`        | `Task<Res> A(IAsyncStreamReader<Req> requestStream, ...)`                     | `AsyncClientStreamingCall<Req, Res> A(...)` |
| `rpc A (stream Req) returns (stream Res)` | `Task A(IAsyncStreamReader<Req> requestStream, IServerStreamWriter<Res> ...)` | `AsyncDuplexStreamingCall<Req, Res> A(...)` |

Applications compiling generated C# service files must provide `Grpc.Core.Api`
and their chosen .NET gRPC hosting or client package, such as `Grpc.AspNetCore`
or `Grpc.Net.Client`. The `Apache.Fory` package does not add gRPC dependencies
as hard dependencies.

## JavaScript/TypeScript

### Output Layout

JavaScript/TypeScript output is one `.ts` file per schema, for example:

- `<javascript_out>/addressbook.ts`

When the schema contains services, JavaScript can also emit service companions:

- `<javascript_out>/addressbook_grpc.ts` with `--grpc`
- `<javascript_out>/addressbook_grpc_web.ts` with `--grpc-web`

### Type Generation

Messages generate `export interface` declarations with camelCase field names:

```typescript
export interface Person {
  name: string;
  id: number;
  phones: PhoneNumber[];
  pet?: Animal | null;
}
```

Enums generate `export enum` declarations:

```typescript
export enum PhoneType {
  MOBILE = 0,
  HOME = 1,
  WORK = 2,
}
```

Unions generate a discriminated union with a case enum:

```typescript
export enum AnimalCase {
  DOG = 1,
  CAT = 2,
}

export type Animal =
  | { case: AnimalCase.DOG; value: Dog }
  | { case: AnimalCase.CAT; value: Cat };
```

### Schema Helpers

Each generated model file exports a registration helper for custom `Fory`
instances and root serialization helpers. The public API looks like:

```typescript
import type Fory, { Serializer } from "@apache-fory/core";

export function registerAddressbookTypes(fory: Fory): {
  person: {
    serialize: (value: Person | null) => Uint8Array;
    deserialize: (bytes: Uint8Array) => Person;
    serializer: Serializer;
  };
};
export const serializePerson: (value: Person | null) => Uint8Array;
export const deserializePerson: (bytes: Uint8Array) => Person;
```

Imported schema modules are registered automatically by `registerXxxTypes(fory)`.
Use `serializeX` and `deserializeX` for the generated default serialization
path. Call `registerXxxTypes(fory)` when the application manages its own `Fory`
instance. Generated gRPC companions import the generated helpers automatically.

### gRPC Service Companions

When a schema contains services and the compiler is run with `--grpc`,
JavaScript generation emits a Node.js companion named `<module>_grpc.ts`.
The file contains service descriptors, handler interfaces, a client class, and a
server registration helper for `@grpc/grpc-js`.

```typescript
export interface GreeterHandlers extends grpc.UntypedServiceImplementation {
  sayHello: grpc.handleUnaryCall<HelloRequest, HelloReply>;
}

export function addGreeterService(
  server: grpc.Server,
  handlers: GreeterHandlers,
): void { ... }

export class GreeterClient extends grpc.Client { ... }
```

When the compiler is run with `--grpc-web`, JavaScript generation emits a
browser companion named `<module>_grpc_web.ts`. It contains callback clients for
`grpc-web`; services with unary RPCs also get promise clients:

```typescript
export class GreeterWebClient { ... }

export class GreeterWebPromiseClient { ... }
```

Node.js service companions import `@grpc/grpc-js`; browser companions import
`grpc-web`. Add those packages to the application that compiles or runs the
generated files.

## Swift

### Output Layout

Swift output is one `.swift` file per schema, for example:

- `<swift_out>/addressbook/addressbook.swift`

### Type Generation

The generator creates Swift models with split model macros and stable field/case IDs.
A typed union must include `@ForyUnknownCase case unknown(UnknownCase)` and at
least one non-`unknown` case; `unknown(UnknownCase)` is only the
Fory-provided forward-compatibility carrier. The marker only selects the carrier
and does not add an entry to the schema case table.

When package/namespace is non-empty, namespace shaping is controlled by `swift_namespace_style`:

- `enum` (default): nested enum namespace wrappers.
- `flatten`: package-derived prefix on top-level type names (for example `Demo_Foo_User`).

When package/namespace is empty, no enum wrapper or flatten prefix is applied.

For non-empty package with default `enum` style:

```swift
public enum Addressbook {
    @ForyUnion
    public enum Animal {
        @ForyUnknownCase
        case unknown(UnknownCase)
        @ForyCase(id: 0)
        case dog(Addressbook.Dog)
        @ForyCase(id: 1)
        case cat(Addressbook.Cat)
    }

    @ForyStruct
    public struct Person: Equatable {
        @ForyField(id: 1)
        public var name: String = ""
        @ForyField(id: 8)
        public var pet: Addressbook.Animal = .foryDefault()
    }
}
```

For non-empty package with `flatten` style:

```swift
@ForyStruct
public struct Addressbook_Person: Equatable { ... }
```

The CLI flag `--swift_namespace_style` overrides schema option `swift_namespace_style` when both are set.

Unions are generated as tagged Swift enums with associated payload values.
Messages with `ref`/`weak_ref` fields are generated as `final class` models to preserve reference semantics.
Fixed or tagged integer encodings inside list/map fields are emitted as Swift
field type hints, for example `@ListField(element: .encoding(.fixed))` or
`@MapField(value: .encoding(.tagged))`.
For non-null fixed-width integer list elements, Swift classifies the field as
the corresponding Fory primitive packed-array type; fixed-width integer sets
remain Fory sets.

### Module Installation

Each schema includes a `ForyModule` owner with transitive import installation:

```swift
public enum ForyModule {
    public static func install(_ fory: Fory) throws {
        try ComplexPb.ForyModule.install(fory)
        fory.register(Addressbook.Person.self, id: 100)
        fory.register(Addressbook.Animal.self, id: 106)
    }
}
```

With non-empty package and `flatten` style, the helper is prefixed too (for example `Addressbook_ForyModule`).

For schemas without explicit `[id=...]`, installation uses computed numeric IDs.
If `option enable_auto_type_id = false;` is set, generated code uses name-based registration APIs.

## Dart

### Output Layout

Dart output is two files per schema: a main `.dart` file with annotated types and the IDL module owner, and a `.fory.dart` part file with generated serializers and metadata.

- `<dart_out>/package/package.dart`
- `<dart_out>/package/package.fory.dart`

### Type Generation

Messages generate `@ForyStruct` annotated `final class` declarations with `@ForyField` on each field:

```dart
@ForyStruct()
final class Person {
  Person();

  @ForyField(id: 1)
  String name = '';

  @ForyField(id: 2, type: Int32Type())
  int id = 0;

  @ForyField(id: 7)
  List<Person_PhoneNumber> phones = <Person_PhoneNumber>[];

  @ForyField(id: 8)
  Animal pet = Animal._empty();
}
```

Enums generate Dart `enum` declarations with a `rawValue` getter and `fromRawValue` factory:

```dart
enum Person_PhoneType {
  mobile,
  home,
  work;

  int get rawValue => switch (this) {
    Person_PhoneType.mobile => 0,
    Person_PhoneType.home => 1,
    Person_PhoneType.work => 2,
  };

  static Person_PhoneType fromRawValue(int value) => switch (value) {
    0 => Person_PhoneType.mobile,
    1 => Person_PhoneType.home,
    2 => Person_PhoneType.work,
    _ => throw StateError('Unknown Person_PhoneType raw value $value.'),
  };
}
```

Unions generate `@ForyUnion` annotated classes with factory constructors, a case enum, and a custom serializer:

```dart
enum AnimalCase {
  dog,
  cat;

  int get id => switch (this) {
    AnimalCase.dog => 1,
    AnimalCase.cat => 2,
  };
}

@ForyUnion()
final class Animal {
  final AnimalCase _case;
  final Object? _value;

  const Animal._(this._case, this._value);

  factory Animal.dog(Dog value) => Animal._(AnimalCase.dog, value);
  factory Animal.cat(Cat value) => Animal._(AnimalCase.cat, value);

  bool get isDog => _case == AnimalCase.dog;
  Dog get dogValue => _value as Dog;
  // ...
}
```

Nested types use flat underscore naming (e.g., `Person_PhoneNumber`, `Person_PhoneType`).

`list<T>` fields generate ordered collection carriers and use the Fory list
protocol. `array<T>` fields generate dense one-dimensional bool or numeric
carriers and use the specialized dense-array protocol. Generated code must not
choose `array<T>` only because a language has an optimized list-like carrier;
the schema kind comes from the IDL.

| IDL schema          | Dart generated carrier | Notes                                      |
| ------------------- | ---------------------- | ------------------------------------------ |
| `list<int32>`       | `List<int>`            | List protocol, varint element encoding     |
| `list<fixed int32>` | `List<int>`            | List protocol, fixed-width element segment |
| `array<bool>`       | `BoolList`             | One byte per bool                          |
| `array<int8>`       | `Int8List`             | Dense signed bytes                         |
| `array<int16>`      | `Int16List`            | Dense little-endian int16                  |
| `array<int32>`      | `Int32List`            | Dense little-endian int32                  |
| `array<int64>`      | `Int64List`            | Dense little-endian int64                  |
| `array<uint8>`      | `Uint8List`            | Dense unsigned bytes                       |
| `array<uint16>`     | `Uint16List`           | Dense little-endian uint16                 |
| `array<uint32>`     | `Uint32List`           | Dense little-endian uint32                 |
| `array<uint64>`     | `Uint64List`           | Dense little-endian uint64                 |
| `array<float16>`    | `Float16List`          | Dense binary16 storage                     |
| `array<bfloat16>`   | `Bfloat16List`         | Dense bfloat16 storage                     |
| `array<float32>`    | `Float32List`          | Dense little-endian float32                |
| `array<float64>`    | `Float64List`          | Dense little-endian float64                |

Generated Dart fields that use `ArrayType(element: BoolType())` must use
`BoolList`; plain `List<bool>` remains the generated and handwritten carrier
for `list<bool>`.

Reference tracking on list elements or map values uses the container sugar annotations:

```dart
@ListField(element: DeclaredType(ref: true))
@ForyField(id: 3)
List<Node> children = <Node>[];

@MapField(value: DeclaredType(ref: true))
@ForyField(id: 2)
Map<String, Node> byName = <String, Node>{};
```

### Module Installation

Each generated Dart IDL library includes a module owner named after the input
file, such as `AddressbookForyModule` for `addressbook.dart`. The module
installs imported modules first and then registers every local schema type with
its default IDL identity:

```dart
abstract final class AddressbookForyModule {
  static void install(Fory fory) {
    complex_pb.ComplexPbForyModule.install(fory);
    _registerType(fory, Person);
    _registerType(fory, Dog);
  }

  static Fory getFory() { ... }

  static void _registerType(Fory fory, Type type) {
    if (type == Person) {
      registerGeneratedStruct(fory, _personForySchema, id: 100, namespace: null, typeName: null);
      return;
    }
    // ... other types
  }
}
```

### Usage

```dart
import 'package:fory/fory.dart';
import 'generated/addressbook/addressbook.dart';

void main() {
  final fory = Fory();
  AddressbookForyModule.install(fory);

  final person = Person()
    ..name = 'Alice'
    ..id = 1;

  final bytes = fory.serialize(person);
  final roundTrip = fory.deserialize<Person>(bytes);
}
```

### gRPC Service Companions

When a schema contains services and the compiler is run with `--grpc`, Dart
generation emits one `<module>_grpc.dart` file per schema next to the model
types. It targets `package:grpc`. Request and response serialization uses a Fory
runtime the companion obtains automatically and that registers the schema's
types on first use, so no manual registration is required; an application may
optionally inject a custom `Fory` via the schema module's `install(...)` before
the first call.

All four RPC modes are generated: unary, server-streaming, client-streaming, and
bidirectional. The client class extends `Client`; the service base class extends
`Service` and self-registers each method with `$addMethod`.

```dart
class GreeterClient extends Client {
  // Single response: ResponseFuture. Streaming response: ResponseStream.
  ResponseFuture<HelloReply> sayHello(HelloRequest request, {CallOptions? options}) { ... }
  ResponseStream<HelloReply> sayHellos(HelloRequest request, {CallOptions? options}) { ... }
  ResponseFuture<HelloReply> collectHellos(Stream<HelloRequest> request, {CallOptions? options}) { ... }
  ResponseStream<HelloReply> chatHellos(Stream<HelloRequest> request, {CallOptions? options}) { ... }
}

abstract class GreeterServiceBase extends Service {
  Future<HelloReply> sayHello(ServiceCall call, HelloRequest request);
  Stream<HelloReply> sayHellos(ServiceCall call, HelloRequest request);
  Future<HelloReply> collectHellos(ServiceCall call, Stream<HelloRequest> request);
  Stream<HelloReply> chatHellos(ServiceCall call, Stream<HelloRequest> request);
}
```

A single-response client method returns `ResponseFuture<R>` (client-streaming
adapts the streaming call with `.single`); a streaming-response method returns
`ResponseStream<R>`. On the server, implementations override the abstract methods,
which receive a single request as `Q` and a client-streaming request as
`Stream<Q>`, and return a `Future` for single responses or a `Stream` for
streaming responses.
Applications compiling these files must provide a `grpc` dependency; the Fory Dart
runtime does not add one. The original IDL method names are used in the gRPC wire
paths.

## Kotlin

The Kotlin target emits Kotlin source only. The compiler does not generate Java
files.

### Output Layout

For source file `addressbook.fdl` with `package addressbook`, Kotlin output is
generated under:

- `<kotlin_out>/addressbook/`
- Type files: `AddressBook.kt`, `Person.kt`, `Dog.kt`, `Cat.kt`, `Animal.kt`
- Schema module: `AddressbookForyModule.kt`

The schema module name is derived from the source file stem. Schemas in the same
Kotlin package need distinct generated file names; duplicate generated Kotlin
file paths are rejected before files are written.

If `option kotlin_package = "...";` is present, the output path and Kotlin
package use that option. Otherwise Kotlin uses the FDL package. A Kotlin import
graph cannot mix default-package schemas with named Kotlin packages.
Registration still uses the FDL package so cross-language type names stay
stable.

### Type Generation

Messages generate Kotlin `data class` declarations by default:

```kotlin
@ForyStruct
public data class Person(
  @field:ForyField(id = 1)
  public val name: String,

  @field:ForyField(id = 7)
  public val phones: List<PersonPhoneNumber>,

  @field:ForyField(id = 8)
  public val pet: Animal,
) {
  public fun toBytes(): ByteArray = AddressbookForyModule.getFory().serialize(this)

  public companion object {
    public fun fromBytes(bytes: ByteArray): Person =
      AddressbookForyModule.getFory().deserialize(bytes, Person::class.java)
  }
}
```

Messages that participate in compiler-detected construction cycles generate
normal mutable classes so the generated serializer can publish the instance
before reading back-references:

```kotlin
@ForyStruct
public class Node() {
  @ForyField(id = 1)
  public var id: String = ""

  @Ref
  @ForyField(id = 2)
  public var parent: Node? = null
}
```

Generated Kotlin IDL sources express nullability with Kotlin `?`, not Fory
`@Nullable`, including mutable classes emitted for compiler-detected
construction cycles.

Enums generate Kotlin enum classes with stable Fory enum IDs. Unions generate
sealed classes with `@ForyUnion`; the Fory-provided `Unknown(UnknownCase)`
carrier is marked with `@ForyUnknownCase`. The marker only selects the carrier
and does not add an entry to the schema case table. Schema-defined cases may use
case IDs `0..N` and hold a single `value` property. A typed union must have at
least one non-`Unknown` case.

```kotlin
package addressbook

import org.apache.fory.annotation.ForyCase
import org.apache.fory.annotation.ForyUnion
import org.apache.fory.annotation.ForyUnknownCase
import org.apache.fory.type.union.UnknownCase

@ForyUnion
public sealed class Animal {
  @ForyUnknownCase
  public data class Unknown(public val value: UnknownCase) : Animal()

  @ForyCase(id = 0)
  public data class Dog(public val value: addressbook.Dog) : Animal()
}
```

Packaged Kotlin output keeps the schema case name and qualifies the payload
type when both have the same simple name. If a target output mode cannot express
a legal qualifier for a conflict, the compiler appends `Case` to the generated
case class name.

Kotlin `int32`, `int64`, `uint32`, and `uint64` fields use xlang varint
encoding by default, so generated Kotlin does not emit `@VarInt` for the
default case. It emits `@Fixed` or `@Tagged` only when the schema requests that
non-default encoding. `duration` maps to `kotlin.time.Duration`, and infinite
durations are rejected when encoded. Dense `array<float16>` and
`array<bfloat16>` use the Java core `Float16Array` and `BFloat16Array`
carriers. Generated Kotlin IDL uses `@ArrayType ByteArray` for `array<int8>`,
including nested positions.

### Schema Module

Generated schema modules register schema types and resolve KSP-generated
serializers from the target class name. The package-owned helper Fory instance uses
`ForyKotlin.builder().withXlang(true)` with the schema module installed, so message
`toBytes`/`fromBytes` helpers work without caller-managed Fory setup. For
`addressbook.fdl`:

```kotlin
public object AddressbookForyModule : ForyModule {
  private val fory: ThreadSafeFory by lazy {
    ForyKotlin.builder()
      .withXlang(true)
      .withRefTracking(true)
      .withModule(this)
      .buildThreadSafeFory()
  }

  internal fun getFory(): ThreadSafeFory = fory

  override fun install(fory: Fory) {
    KotlinSerializers.registerType(fory, Person::class.java, 100L)
    KotlinSerializers.registerSerializer(fory, Person::class.java)
    KotlinSerializers.registerUnion(fory, Animal::class.java, 106L)
  }
}
```

`registerUnion` discovers the generated `<Target>_ForySerializer`; callers do
not pass a serializer instance.

### gRPC Service Companions

When a schema contains services and the compiler is run with `--grpc`, Kotlin
generation emits one `<ServiceName>GrpcKt.kt` file per service next to the model
types. The file contains a grpc-kotlin coroutine companion object, not Java
`*Grpc.java` source.

```kotlin
public object AddressBookServiceGrpcKt {
  public const val SERVICE_NAME: String = "addressbook.AddressBookService"

  @JvmStatic
  public val serviceDescriptor: io.grpc.ServiceDescriptor
    get() = serviceDescriptorValue

  @JvmStatic
  public val lookupMethod: io.grpc.MethodDescriptor<Person, AddressBook>
    get() = lookupMethodValue

  public abstract class AddressBookServiceCoroutineImplBase(
    coroutineContext: kotlin.coroutines.CoroutineContext =
      kotlin.coroutines.EmptyCoroutineContext,
  ) : io.grpc.kotlin.AbstractCoroutineServerImpl(coroutineContext) {
    public open suspend fun lookup(request: Person): AddressBook =
      throw io.grpc.StatusException(
        io.grpc.Status.UNIMPLEMENTED.withDescription(
          "Method addressbook.AddressBookService/Lookup is unimplemented",
        ),
      )
  }

  public class AddressBookServiceCoroutineStub @JvmOverloads constructor(
    channel: io.grpc.Channel,
    callOptions: io.grpc.CallOptions = io.grpc.CallOptions.DEFAULT,
  ) : io.grpc.kotlin.AbstractCoroutineStub<AddressBookServiceCoroutineStub>(
    channel,
    callOptions,
  ) {
    public suspend fun lookup(
      request: Person,
      headers: io.grpc.Metadata = io.grpc.Metadata(),
    ): AddressBook =
      io.grpc.kotlin.ClientCalls.unaryRpc(
        channel,
        lookupMethod,
        request,
        callOptions,
        headers,
      )
  }
}
```

Streaming RPCs use `kotlinx.coroutines.flow.Flow`:

| IDL shape                                 | Server method                             | Client method                             |
| ----------------------------------------- | ----------------------------------------- | ----------------------------------------- |
| `rpc A (Req) returns (Res)`               | `suspend fun a(request: Req): Res`        | `suspend fun a(request: Req): Res`        |
| `rpc A (Req) returns (stream Res)`        | `fun a(request: Req): Flow<Res>`          | `fun a(request: Req): Flow<Res>`          |
| `rpc A (stream Req) returns (Res)`        | `suspend fun a(requests: Flow<Req>): Res` | `suspend fun a(requests: Flow<Req>): Res` |
| `rpc A (stream Req) returns (stream Res)` | `fun a(requests: Flow<Req>): Flow<Res>`   | `fun a(requests: Flow<Req>): Flow<Res>`   |

Each method descriptor uses a Fory-backed `io.grpc.MethodDescriptor.Marshaller`
that reuses the generated schema module's `ThreadSafeFory`. Generated service
companions do not call protobuf parsers, do not expose KSP serializer class
names, and do not create Fory instances per call.

Applications compiling the generated Kotlin service files must provide
grpc-java, grpc-kotlin, and `kotlinx-coroutines-core` dependencies. Fory Kotlin
artifacts do not add those gRPC dependencies as hard dependencies.

## Scala

The Scala target emits Scala 3 source only. The `fory-scala` artifact still
supports Scala 2.13 and Scala 3, but generated IDL source and macro derivation
require Scala 3.

### Output Layout

For `package addressbook`, Scala output is generated under:

- `<scala_out>/addressbook/`
- Type files: `AddressBook.scala`, `Person.scala`, `Dog.scala`, `Cat.scala`, `Animal.scala`
- Schema module: `AddressbookForyModule.scala`

For schemas without a Scala package, the schema module name is derived from the
source file stem, for example `main.fdl` generates `MainForyModule.scala`.
Scala import graphs cannot mix default-package schemas with named Scala
packages.

### Type Generation

Messages outside compiler-detected construction cycles generate case classes:

```scala
import org.apache.fory.annotation.{ForyField, ForyStruct}
import org.apache.fory.scala.ForySerializer

@ForyStruct
final case class Person(
  @ForyField(id = 1) name: String,
  @ForyField(id = 3) email: Option[String],
  @ForyField(id = 7) phones: List[Person.PhoneNumber],
  @ForyField(id = 8) pet: Animal
) derives ForySerializer {
  def toBytes(): Array[Byte] =
    AddressbookForyModule.getFory.serialize(this)
}

object Person {
  def fromBytes(bytes: Array[Byte]): Person =
    AddressbookForyModule.getFory.deserialize(bytes).asInstanceOf[Person]
}
```

Messages in circular construction cycles generate normal classes with mutable
serialized fields so reads can register the object before reading back-references:

```scala
import org.apache.fory.annotation.{ForyField, ForyStruct, Ref}
import org.apache.fory.scala.ForySerializer

@ForyStruct
final class Node() derives ForySerializer {
  @ForyField(id = 1)
  var id: String = ""

  @Ref
  @ForyField(id = 2)
  var parent: Option[Node] = None
}
```

Enums generate Scala 3 enums with stable Fory IDs:

```scala
import org.apache.fory.annotation.ForyEnumId

enum PhoneType {
  @ForyEnumId(0)
  case Mobile

  @ForyEnumId(1)
  case Home

  @ForyEnumId(2)
  case Work
}
```

Unions generate Scala 3 ADT enums. `Unknown(UnknownCase)` is the Fory-provided
forward-compatibility carrier marked with `@ForyUnknownCase`. It is omitted
from the schema case table because the marker only selects the carrier and does
not add a schema entry. Schema-defined cases use non-negative `@ForyCase` IDs.
A typed union must have at least one
non-`Unknown` case.

```scala
package addressbook

import org.apache.fory.annotation.{ForyCase, ForyUnion, ForyUnknownCase}
import org.apache.fory.scala.ForySerializer
import org.apache.fory.`type`.union.UnknownCase

@ForyUnion
enum Animal derives ForySerializer {
  @ForyUnknownCase
  case Unknown(value: UnknownCase)

  @ForyCase(id = 0)
  case Dog(value: _root_.addressbook.Dog)

  @ForyCase(id = 1)
  case Cat(value: _root_.addressbook.Cat)
}
```

Packaged Scala output keeps the schema case name and qualifies the payload type
when both have the same simple name. If a target output mode cannot express a
legal qualifier for a conflict, the compiler appends `Case` to the generated
case name.

`optional T` fields generate `Option[T]`. Top-level message references use
`@Ref` on the field or constructor parameter. Nested element/value references
use type-use annotations such as `List[Node @Ref]`.

### Schema Module

Generated schema modules register schema serializers, enums, structs, and
unions. The package-owned helper Fory instance uses
`ForyScala.builder().withXlang(true)` with the schema module installed, so
message `toBytes`/`fromBytes` helpers work without caller-managed Fory setup:

```scala
object AddressbookForyModule extends org.apache.fory.ForyModule {
  private lazy val fory: ThreadSafeFory =
    ForyScala.builder()
      .withXlang(true)
      .withRefTracking(true)
      .withModule(this)
      .buildThreadSafeFory()

  private[addressbook] def getFory: ThreadSafeFory = fory

  override def install(fory: Fory): Unit = {
    ScalaSerializers.registerEnum(fory, classOf[Person.PhoneType], 101L)
    ForySerializer.register(fory, classOf[Person.PhoneNumber], 102L)
    ForySerializer.register(fory, classOf[Person], 100L)
    ForySerializer.register(fory, classOf[Animal], 106L)
  }
}
```

### gRPC Service Companions

When a schema contains services and the compiler is run with `--grpc`, Scala
generation emits one `<ServiceName>Grpc.scala` companion per local service
definition. The companion lives in the same Scala package as the generated
models and schema module.

For a service such as:

```protobuf
service AddressBookService {
  rpc Lookup (Person) returns (AddressBook);
  rpc Watch (Person) returns (stream AddressBook);
  rpc Upload (stream Person) returns (AddressBook);
  rpc Chat (stream Person) returns (stream AddressBook);
}
```

the generated companion contains:

- `SERVICE_NAME` and grpc-java method descriptors
- `AddressBookServiceImplBase` for server implementations
- `AddressBookServiceClient` for client calls
- Fory-backed grpc-java marshallers for request and response payloads

The generated Scala client keeps grpc-java available per method while adding
Scala-friendly convenience methods for the shapes where a direct Scala handle
can preserve the needed lifecycle controls:

| RPC shape                                               | Scala convenience method            | grpc-java-style method                           |
| ------------------------------------------------------- | ----------------------------------- | ------------------------------------------------ |
| `rpc Lookup (Person) returns (AddressBook)`             | `lookup(request): RpcFuture[Resp]`  | async observer, blocking, and `ListenableFuture` |
| `rpc Watch (Person) returns (stream AddressBook)`       | `watch(request): RpcIterator[Resp]` | async observer and blocking iterator             |
| `rpc Upload (stream Person) returns (AddressBook)`      | None                                | request `StreamObserver`                         |
| `rpc Chat (stream Person) returns (stream AddressBook)` | None                                | request and response `StreamObserver`            |

Unary client convenience methods return `org.apache.fory.scala.rpc.RpcFuture`:

```scala
val client = AddressBookServiceGrpc.newClient(channel)
val call = client.lookup(person)
call.asFuture.foreach(handleAddressBook)(scala.concurrent.ExecutionContext.global)
```

Server-streaming client convenience methods return
`org.apache.fory.scala.rpc.RpcIterator`:

```scala
val stream = client.watch(person)
try {
  while (stream.hasNext) {
    handleAddressBook(stream.next())
  }
} finally {
  stream.close()
}
```

Close or cancel the `RpcIterator` when the client stops before consuming the
whole stream. The generated adapter cancels the underlying gRPC call so the
server is not left writing a response stream the client no longer reads.

Client-streaming and bidirectional methods use grpc-java `StreamObserver` APIs:

```scala
val requestStream = client.upload(
  new io.grpc.stub.StreamObserver[AddressBook] {
    override def onNext(value: AddressBook): Unit = handleAddressBook(value)
    override def onError(t: Throwable): Unit = handleError(t)
    override def onCompleted(): Unit = ()
  }
)
requestStream.onNext(person)
requestStream.onCompleted()
```

Server implementations mirror grpc-java. Unary methods can override the direct
request-to-response method generated by Scala, but streaming methods override
observer-based methods and must call `onNext`, `onError`, and `onCompleted`
according to grpc-java lifecycle rules.

Applications compiling generated Scala gRPC companions must provide grpc-java
dependencies such as `grpc-api`, `grpc-stub`, and a transport like
`grpc-netty-shaded`. The `fory-scala` artifact does not add grpc-java as a hard
dependency.

## Cross-Language Notes

### Type ID Behavior

- Explicit `[id=...]` values are used directly by generated module installation or registration helpers.
- When type IDs are omitted, generated code uses computed numeric IDs (see `auto_id.*` outputs).
- If `option enable_auto_type_id = false;` is set, generated module installation or registration helpers use name-based APIs instead of numeric IDs.

### Nested Type Shape

| Language              | Nested type form               |
| --------------------- | ------------------------------ |
| Java                  | `Person.PhoneNumber`           |
| Python                | `Person.PhoneNumber`           |
| Rust                  | `person::PhoneNumber`          |
| C++                   | `Person::PhoneNumber`          |
| Go                    | `Person_PhoneNumber` (default) |
| C#                    | `Person.PhoneNumber`           |
| JavaScript/TypeScript | `Person.PhoneNumber`           |
| Swift                 | `Person.PhoneNumber`           |
| Dart                  | `Person_PhoneNumber`           |
| Kotlin                | `PersonPhoneNumber`            |
| Scala                 | `Person.PhoneNumber`           |

### Byte Helper Naming

| Language              | Helpers                   |
| --------------------- | ------------------------- |
| Java                  | `toBytes` / `fromBytes`   |
| Kotlin                | `toBytes` / `fromBytes`   |
| Scala                 | `toBytes` / `fromBytes`   |
| Python                | `to_bytes` / `from_bytes` |
| Rust                  | `to_bytes` / `from_bytes` |
| C++                   | `to_bytes` / `from_bytes` |
| Go                    | `ToBytes` / `FromBytes`   |
| C#                    | `ToBytes` / `FromBytes`   |
| JavaScript/TypeScript | (via `fory.serialize()`)  |
| Swift                 | `toBytes` / `fromBytes`   |
| Dart                  | (via `fory.serialize()`)  |
