๐Ÿ“ฆ apache / fory

๐Ÿ“„ index.md ยท 207 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207---
title: Overview
sidebar_position: 1
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.
---

Fory Definition Language (FDL) is a schema definition language for Apache Fory that enables type-safe cross-language serialization. Define your data structures once and generate native data structure code for Java, Python, Go, Rust, and C++.

## Overview

FDL provides a simple, intuitive syntax for defining cross-language data structures:

```protobuf
package example;

enum Status [id=100] {
    PENDING = 0;
    ACTIVE = 1;
    COMPLETED = 2;
}

message User [id=101] {
    string name = 1;
    int32 age = 2;
    optional string email = 3;
    repeated string tags = 4;
}

message Order [id=102] {
    ref User customer = 1;
    repeated Item items = 2;
    Status status = 3;
    map<string, int32> metadata = 4;
}
```

## Why FDL?

### Schema-First Development

Define your data model once in FDL and generate consistent, type-safe code across all languages. This ensures:

- **Type Safety**: Catch type errors at compile time, not runtime
- **Consistency**: All languages use the same field names, types, and structures
- **Documentation**: Schema serves as living documentation
- **Evolution**: Managed schema changes across all implementations

### Fory-Native Features

Unlike generic IDLs, FDL is designed specifically for Fory serialization:

- **Reference Tracking**: First-class support for shared and circular references via `ref`
- **Nullable Fields**: Explicit `optional` modifier for nullable types
- **Type Registration**: Built-in support for both numeric IDs and namespace-based registration
- **Native Code Generation**: Generates idiomatic code with Fory annotations/macros

### Zero Runtime Overhead

Generated code uses native language constructs:

- Java: Plain POJOs with `@ForyField` annotations
- Python: Dataclasses with type hints
- Go: Structs with struct tags
- Rust: Structs with `#[derive(ForyObject)]`
- C++: Structs with `FORY_STRUCT` macros

## Quick Start

### 1. Install the Compiler

```bash
cd compiler
pip install -e .
```

### 2. Write Your Schema

Create `example.fdl`:

```protobuf
package example;

message Person [id=100] {
    string name = 1;
    int32 age = 2;
    optional string email = 3;
}
```

### 3. Generate Code

```bash
# Generate for all languages
fory compile example.fdl --output ./generated

# Generate for specific languages
fory compile example.fdl --lang java,python --output ./generated
```

### 4. Use Generated Code

**Java:**

```java
Fory fory = Fory.builder().withLanguage(Language.XLANG).build();
ExampleForyRegistration.register(fory);

Person person = new Person();
person.setName("Alice");
person.setAge(30);
byte[] data = fory.serialize(person);
```

**Python:**

```python
import pyfory
from example import Person, register_example_types

fory = pyfory.Fory()
register_example_types(fory)

person = Person(name="Alice", age=30)
data = fory.serialize(person)
```

## Documentation

| Document                                   | Description                                  |
| ------------------------------------------ | -------------------------------------------- |
| [FDL Syntax Reference](fdl-syntax.md)      | Complete language syntax and grammar         |
| [Type System](type-system.md)              | Primitive types, collections, and type rules |
| [Compiler Guide](compiler-guide.md)        | CLI options and build integration            |
| [Generated Code](generated-code.md)        | Output format for each target language       |
| [Protocol Buffers vs FDL](protobuf-idl.md) | Comparison with protobuf and migration guide |

## Key Concepts

### Type Registration

FDL supports two registration modes:

**Numeric Type IDs** - Fast and compact:

```protobuf
message User [id=100] { ... }  // Registered with ID 100
```

**Namespace-based** - Flexible and readable:

```protobuf
message Config { ... }  // Registered as "package.Config"
```

### Field Modifiers

- **`optional`**: Field can be null/None
- **`ref`**: Enable reference tracking for shared/circular references
- **`repeated`**: Field is a list/array

```protobuf
message Example {
    optional string nullable = 1;
    ref Node parent = 2;
    repeated int32 numbers = 3;
}
```

### Cross-Language Compatibility

FDL types map to native types in each language:

| FDL Type | Java      | Python | Go       | Rust     | C++           |
| -------- | --------- | ------ | -------- | -------- | ------------- |
| `int32`  | `int`     | `int`  | `int32`  | `i32`    | `int32_t`     |
| `string` | `String`  | `str`  | `string` | `String` | `std::string` |
| `bool`   | `boolean` | `bool` | `bool`   | `bool`   | `bool`        |

See [Type System](type-system.md) for complete mappings.

## Best Practices

1. **Use meaningful package names**: Group related types together
2. **Assign type IDs for performance**: Numeric IDs are faster than name-based registration
3. **Reserve ID ranges**: Leave gaps for future additions (e.g., 100-199 for users, 200-299 for orders)
4. **Use `optional` explicitly**: Make nullability clear in the schema
5. **Use `ref` for shared objects**: Enable reference tracking when objects are shared

## Examples

See the [examples](https://github.com/apache/fory/tree/main/compiler/examples) directory for complete working examples.