This is an automated email from the ASF dual-hosted git repository.
chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory-site.git
The following commit(s) were added to refs/heads/main by this push:
new 13a7f5acf 🔄 synced local 'docs/compiler/' with remote 'docs/compiler/'
13a7f5acf is described below
commit 13a7f5acfae158f3196ea9020418cdd255c74471
Author: chaokunyang <[email protected]>
AuthorDate: Wed Jan 21 08:58:44 2026 +0000
🔄 synced local 'docs/compiler/' with remote 'docs/compiler/'
---
docs/compiler/protobuf-idl.md | 501 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 501 insertions(+)
diff --git a/docs/compiler/protobuf-idl.md b/docs/compiler/protobuf-idl.md
new file mode 100644
index 000000000..0971b4a92
--- /dev/null
+++ b/docs/compiler/protobuf-idl.md
@@ -0,0 +1,501 @@
+---
+title: Protocol Buffers IDL
+sidebar_position: 10
+id: protobuf_idl_support
+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 compares Google's Protocol Buffers (protobuf) with Fory
Definition Language (FDL), helping you understand when to use each and how to
migrate between them.
+
+## Overview
+
+| Aspect | Protocol Buffers | FDL
|
+| ---------------------- | --------------------------------- |
----------------------------------- |
+| **Primary Purpose** | RPC and message interchange | Cross-language
object serialization |
+| **Design Philosophy** | Schema evolution, backward compat | Performance,
native integration |
+| **Reference Tracking** | Not supported | First-class
support (`ref`) |
+| **Generated Code** | Custom message types | Native language
constructs |
+| **Serialization** | Tag-length-value encoding | Fory binary
protocol |
+| **Performance** | Good | Excellent (up
to 170x faster) |
+
+## Syntax Comparison
+
+### Package Declaration
+
+**Protocol Buffers:**
+
+```protobuf
+syntax = "proto3";
+package example.models;
+option java_package = "com.example.models";
+option go_package = "example.com/models";
+```
+
+**FDL:**
+
+```protobuf
+package example.models;
+```
+
+FDL uses a single package declaration that maps to all languages automatically.
+
+### Enum Definition
+
+**Protocol Buffers:**
+
+```protobuf
+enum Status {
+ STATUS_UNSPECIFIED = 0;
+ STATUS_PENDING = 1;
+ STATUS_ACTIVE = 2;
+ STATUS_COMPLETED = 3;
+}
+```
+
+**FDL:**
+
+```protobuf
+enum Status [id=100] {
+ PENDING = 0;
+ ACTIVE = 1;
+ COMPLETED = 2;
+}
+```
+
+Key differences:
+
+- FDL supports optional type IDs (`[id=100]`) for efficient serialization
+- Protobuf requires `_UNSPECIFIED = 0` by convention; FDL uses explicit values
+- FDL enum values don't require prefixes
+
+### Message Definition
+
+**Protocol Buffers:**
+
+```protobuf
+message User {
+ string id = 1;
+ string name = 2;
+ optional string email = 3;
+ int32 age = 4;
+ repeated string tags = 5;
+ map<string, string> metadata = 6;
+}
+```
+
+**FDL:**
+
+```protobuf
+message User [id=101] {
+ string id = 1;
+ string name = 2;
+ optional string email = 3;
+ int32 age = 4;
+ repeated string tags = 5;
+ map<string, string> metadata = 6;
+}
+```
+
+Syntax is nearly identical, but FDL adds:
+
+- Type IDs (`[id=101]`) for cross-language registration
+- `ref` modifier for reference tracking
+
+### Nested Types
+
+**Protocol Buffers:**
+
+```protobuf
+message Order {
+ message Item {
+ string product_id = 1;
+ int32 quantity = 2;
+ }
+ repeated Item items = 1;
+}
+```
+
+**FDL:**
+
+```protobuf
+message OrderItem [id=200] {
+ string product_id = 1;
+ int32 quantity = 2;
+}
+
+message Order [id=201] {
+ repeated OrderItem items = 1;
+}
+```
+
+FDL supports nested types, but generators may flatten them for languages where
nested types are not idiomatic.
+
+### Imports
+
+**Protocol Buffers:**
+
+```protobuf
+import "other.proto";
+import "google/protobuf/timestamp.proto";
+```
+
+**FDL:**
+
+FDL currently requires all types in a single file or uses forward references
within the same file.
+
+## Feature Comparison
+
+### Reference Tracking
+
+FDL's killer feature is first-class reference tracking:
+
+**FDL:**
+
+```protobuf
+message TreeNode [id=300] {
+ string value = 1;
+ ref TreeNode parent = 2;
+ repeated ref TreeNode children = 3; // Element refs
+ ref repeated TreeNode path = 4; // Collection ref
+}
+
+message Graph [id=301] {
+ repeated ref Node nodes = 1; // Shared references preserved (elements)
+}
+```
+
+**Protocol Buffers:**
+
+Protobuf cannot represent circular or shared references. You must use
workarounds:
+
+```protobuf
+// Workaround: Use IDs instead of references
+message TreeNode {
+ string id = 1;
+ string value = 2;
+ string parent_id = 3; // Manual ID reference
+ repeated string child_ids = 4;
+}
+```
+
+### Type System
+
+| Type | Protocol Buffers
| FDL |
+| ---------- |
------------------------------------------------------------------------------------------------------
| --------------------------------- |
+| Boolean | `bool`
| `bool` |
+| Integers | `int32`, `int64`, `sint32`, `sint64`, `uint32`, `uint64`,
`fixed32`, `fixed64`, `sfixed32`, `sfixed64` | `int8`, `int16`, `int32`,
`int64` |
+| Floats | `float`, `double`
| `float32`, `float64` |
+| String | `string`
| `string` |
+| Binary | `bytes`
| `bytes` |
+| Timestamp | `google.protobuf.Timestamp`
| `timestamp` |
+| Date | Not built-in
| `date` |
+| Duration | `google.protobuf.Duration`
| Not built-in |
+| List | `repeated T`
| `repeated T` |
+| Map | `map<K, V>`
| `map<K, V>` |
+| Nullable | `optional T` (proto3)
| `optional T` |
+| Oneof | `oneof`
| Not supported |
+| Any | `google.protobuf.Any`
| Not supported |
+| Extensions | `extend`
| Not supported |
+
+### Wire Format
+
+**Protocol Buffers:**
+
+- Tag-length-value encoding
+- Variable-length integers (varints)
+- Field numbers encoded in wire format
+- Unknown fields preserved
+
+**FDL/Fory:**
+
+- Optimized binary format
+- Schema-aware encoding
+- Type IDs for fast lookup
+- Reference tracking support
+- Zero-copy deserialization where possible
+
+### Generated Code Style
+
+**Protocol Buffers** generates custom types with builders and accessors:
+
+```java
+// Protobuf generated Java
+User user = User.newBuilder()
+ .setId("u123")
+ .setName("Alice")
+ .setAge(30)
+ .build();
+```
+
+**FDL** generates native POJOs:
+
+```java
+// FDL generated Java
+User user = new User();
+user.setId("u123");
+user.setName("Alice");
+user.setAge(30);
+```
+
+### Comparison Table
+
+| Feature | Protocol Buffers | FDL |
+| -------------------------- | ----------------- | --------- |
+| Schema evolution | Excellent | Good |
+| Backward compatibility | Excellent | Good |
+| Reference tracking | No | Yes |
+| Circular references | No | Yes |
+| Native code generation | No (custom types) | Yes |
+| Unknown field preservation | Yes | No |
+| Schema-less mode | No | Yes\* |
+| RPC integration (gRPC) | Yes | No |
+| Zero-copy deserialization | Limited | Yes |
+| Human-readable format | JSON, TextFormat | No |
+| Performance | Good | Excellent |
+
+\*Fory supports schema-less serialization without FDL
+
+## When to Use Each
+
+### Use Protocol Buffers When:
+
+1. **Building gRPC services**: Protobuf is the native format for gRPC
+2. **Maximum backward compatibility**: Protobuf's unknown field handling is
robust
+3. **Schema evolution is critical**: Adding/removing fields across versions
+4. **You need oneof/Any types**: Complex polymorphism requirements
+5. **Human-readable debugging**: TextFormat and JSON transcoding available
+6. **Ecosystem integration**: Wide tooling support (linting, documentation)
+
+### Use FDL/Fory When:
+
+1. **Performance is critical**: Up to 170x faster than protobuf
+2. **Cross-language object graphs**: Serialize Java objects, deserialize in
Python
+3. **Circular/shared references**: Object graphs with cycles
+4. **Native code preferred**: Standard POJOs, dataclasses, structs
+5. **Memory efficiency**: Zero-copy deserialization
+6. **Existing object models**: Minimal changes to existing code
+
+## Performance Comparison
+
+Benchmarks show Fory significantly outperforms Protocol Buffers, see more
details from below links:
+
+- Benchmark result: https://fory.apache.org/docs/introduction/benchmark
+- Benchmark code: https://github.com/apache/fory/tree/main/benchmarks
+- Benchmark docs: https://github.com/apache/fory/tree/main/benchmarks
+
+## Migration Guide
+
+### From Protocol Buffers to FDL
+
+#### Step 1: Convert Syntax
+
+**Before (proto):**
+
+```protobuf
+syntax = "proto3";
+package myapp;
+
+message Person {
+ string name = 1;
+ int32 age = 2;
+ repeated string emails = 3;
+ Address address = 4;
+}
+
+message Address {
+ string street = 1;
+ string city = 2;
+}
+```
+
+**After (FDL):**
+
+```protobuf
+package myapp;
+
+message Address [id=100] {
+ string street = 1;
+ string city = 2;
+}
+
+message Person [id=101] {
+ string name = 1;
+ int32 age = 2;
+ repeated string emails = 3;
+ Address address = 4;
+}
+```
+
+#### Step 2: Handle Special Cases
+
+**oneof fields:**
+
+```protobuf
+// Proto
+message Result {
+ oneof result {
+ Success success = 1;
+ Error error = 2;
+ }
+}
+```
+
+```protobuf
+// FDL - Use separate optional fields
+message Result [id=102] {
+ optional Success success = 1;
+ optional Error error = 2;
+}
+// Or model as sealed class hierarchy in generated code
+```
+
+**Well-known types:**
+
+```protobuf
+// Proto
+import "google/protobuf/timestamp.proto";
+message Event {
+ google.protobuf.Timestamp created_at = 1;
+}
+```
+
+```protobuf
+// FDL
+message Event [id=103] {
+ timestamp created_at = 1;
+}
+```
+
+#### Step 3: Add Type IDs
+
+Assign unique type IDs for cross-language compatibility:
+
+```protobuf
+// Reserve ranges for different domains
+// 100-199: Common types
+// 200-299: User domain
+// 300-399: Order domain
+
+message Address [id=100] { ... }
+message Person [id=200] { ... }
+message Order [id=300] { ... }
+```
+
+#### Step 4: Update Build Configuration
+
+**Before (Maven with protobuf):**
+
+```xml
+<plugin>
+ <groupId>org.xolstice.maven.plugins</groupId>
+ <artifactId>protobuf-maven-plugin</artifactId>
+ <!-- ... -->
+</plugin>
+```
+
+**After (Maven with FDL):**
+
+```xml
+<plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>generate-fory-types</id>
+ <phase>generate-sources</phase>
+ <goals><goal>exec</goal></goals>
+ <configuration>
+ <executable>fory</executable>
+ <arguments>
+ <argument>compile</argument>
+ <argument>${project.basedir}/src/main/fdl/schema.fdl</argument>
+ <argument>--lang</argument>
+ <argument>java</argument>
+ <argument>--output</argument>
+ <argument>${project.build.directory}/generated-sources/fdl</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ </executions>
+</plugin>
+```
+
+#### Step 5: Update Application Code
+
+**Before (Protobuf Java):**
+
+```java
+// Protobuf style
+Person.Builder builder = Person.newBuilder();
+builder.setName("Alice");
+builder.setAge(30);
+Person person = builder.build();
+
+byte[] data = person.toByteArray();
+Person restored = Person.parseFrom(data);
+```
+
+**After (Fory Java):**
+
+```java
+// Fory style
+Person person = new Person();
+person.setName("Alice");
+person.setAge(30);
+
+Fory fory = Fory.builder().withLanguage(Language.XLANG).build();
+MyappForyRegistration.register(fory);
+
+byte[] data = fory.serialize(person);
+Person restored = (Person) fory.deserialize(data);
+```
+
+### Coexistence Strategy
+
+For gradual migration, you can run both systems in parallel:
+
+```java
+// Dual serialization during migration
+public byte[] serialize(Object obj, Format format) {
+ if (format == Format.PROTOBUF) {
+ return ((MessageLite) obj).toByteArray();
+ } else {
+ return fory.serialize(obj);
+ }
+}
+
+// Convert between formats
+public ForyPerson fromProto(ProtoPerson proto) {
+ ForyPerson person = new ForyPerson();
+ person.setName(proto.getName());
+ person.setAge(proto.getAge());
+ return person;
+}
+```
+
+## Summary
+
+| Aspect | Choose Protocol Buffers | Choose FDL/Fory |
+| ---------------- | ----------------------- | ---------------------- |
+| Use case | RPC, API contracts | Object serialization |
+| Performance | Acceptable | Critical |
+| References | Not needed | Circular/shared needed |
+| Code style | Builder pattern OK | Native POJOs preferred |
+| Schema evolution | Complex requirements | Simpler requirements |
+| Ecosystem | Need gRPC, tooling | Need raw performance |
+
+Both tools excel in their domains. Protocol Buffers shines for RPC and API
contracts with strong schema evolution guarantees. FDL/Fory excels at
high-performance object serialization with native language integration and
reference tracking support.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]