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
commit ddcc499f5fe17db5f220c9a5d4e2da354e60a82a Author: chaokunyang <[email protected]> AuthorDate: Sat Jun 13 07:36:07 2026 +0000 🔄 synced local 'docs/compiler/' with remote 'docs/compiler/' --- docs/compiler/compiler-guide.md | 17 ++++++--- docs/compiler/flatbuffers-idl.md | 10 ++--- docs/compiler/generated-code.md | 80 +++++++++++++++++++++++++++++++++++++--- docs/compiler/index.md | 15 ++++---- docs/compiler/protobuf-idl.md | 42 +++++++++++---------- docs/compiler/schema-idl.md | 6 +-- 6 files changed, 124 insertions(+), 46 deletions(-) diff --git a/docs/compiler/compiler-guide.md b/docs/compiler/compiler-guide.md index cd1701070c..638c3ad268 100644 --- a/docs/compiler/compiler-guide.md +++ b/docs/compiler/compiler-guide.md @@ -141,22 +141,24 @@ foryc schema.fdl --output ./src/generated foryc user.fdl order.fdl product.fdl --output ./generated ``` -**Compile a simple schema containing service definitions (Java + Python + Rust + Scala + Kotlin models):** +**Compile a simple schema containing service definitions (Java + Python + Rust + C# + Scala + Kotlin models):** ```bash -foryc compiler/examples/service.fdl --java_out=./generated/java --python_out=./generated/python --rust_out=./generated/rust --scala_out=./generated/scala --kotlin_out=./generated/kotlin +foryc compiler/examples/service.fdl --java_out=./generated/java --python_out=./generated/python --rust_out=./generated/rust --csharp_out=./generated/csharp --scala_out=./generated/scala --kotlin_out=./generated/kotlin ``` -**Generate Java, Python, Rust, Scala, and Kotlin gRPC service companions:** +**Generate Java, Python, Rust, C#, Scala, and Kotlin gRPC service companions:** ```bash -foryc compiler/examples/service.fdl --java_out=./generated/java --python_out=./generated/python --rust_out=./generated/rust --scala_out=./generated/scala --kotlin_out=./generated/kotlin --grpc +foryc compiler/examples/service.fdl --java_out=./generated/java --python_out=./generated/python --rust_out=./generated/rust --csharp_out=./generated/csharp --scala_out=./generated/scala --kotlin_out=./generated/kotlin --grpc ``` The generated gRPC service code uses Fory to serialize request and response payloads. Java output imports grpc-java APIs, Python output imports `grpc`, and Rust output imports `tonic` and `bytes`. Scala output imports grpc-java APIs. Kotlin output imports grpc-java and grpc-kotlin APIs and uses coroutine stubs. +C# output imports `Grpc.Core.Api` types and can be hosted with normal .NET gRPC +packages such as `Grpc.AspNetCore` or called through `Grpc.Net.Client`. Applications that compile or run those generated service files must provide their own gRPC dependencies. Fory packages do not add a hard gRPC dependency for this feature. @@ -367,15 +369,18 @@ generated/ generated/ └── csharp/ └── example/ - └── example.cs + └── Example.cs ``` -- Single `.cs` file per schema +- Single `.cs` file per schema named from the normalized PascalCase source file + stem - Namespace uses `csharp_namespace` (if set) or Fory IDL package - Includes source-file-prefixed `XXXForyModule` installation helper and `ToBytes`/`FromBytes` methods - Imported schemas are installed transitively (for example `root.idl` importing `addressbook.fdl` and `tree.fdl`) +- With `--grpc`, one `<ServiceName>Grpc.cs` companion per service next to the + schema file output ### Swift diff --git a/docs/compiler/flatbuffers-idl.md b/docs/compiler/flatbuffers-idl.md index 203a64c405..9a0d3e9a27 100644 --- a/docs/compiler/flatbuffers-idl.md +++ b/docs/compiler/flatbuffers-idl.md @@ -126,7 +126,7 @@ message Container { FlatBuffers `rpc_service` definitions are translated to Fory services. With `--grpc`, the compiler emits gRPC service companions for supported outputs such -as Java, Python, Go, Rust, Scala, and Kotlin. These companions use Fory +as Java, Python, Go, Rust, C#, Scala, and Kotlin. These companions use Fory serialization for request and response payloads. ```fbs @@ -137,13 +137,13 @@ rpc_service SearchService { ``` ```bash -foryc api.fbs --java_out=./generated/java --python_out=./generated/python --rust_out=./generated/rust --scala_out=./generated/scala --kotlin_out=./generated/kotlin --grpc +foryc api.fbs --java_out=./generated/java --python_out=./generated/python --rust_out=./generated/rust --csharp_out=./generated/csharp --scala_out=./generated/scala --kotlin_out=./generated/kotlin --grpc ``` Generated service code imports grpc APIs, so applications must provide grpc-java, -grpc-kotlin, `grpcio`, grpc-go, or Rust `tonic` and `bytes` dependencies when -they compile or run those files. Fory packages do not add gRPC as a hard -dependency. +grpc-kotlin, Scala grpc-java APIs, `grpcio`, grpc-go, Rust `tonic` and `bytes`, +or C# `Grpc.Core.Api` plus server/client dependencies when they compile or run +those files. Fory packages do not add gRPC as a hard dependency. ### Defaults and Metadata diff --git a/docs/compiler/generated-code.md b/docs/compiler/generated-code.md index dfdc403a09..a9035f9aff 100644 --- a/docs/compiler/generated-code.md +++ b/docs/compiler/generated-code.md @@ -23,7 +23,11 @@ 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 schema-file owners, not package or namespace owners. In targets that expose the owner directly in a language package or namespace, the owner name includes a source-file-derived prefix such as `AddressbookForyModule` or `ComplexPbForyModule` so multiple IDL files can target the same package or namespace without producing colliding `ForyModule` types. +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 @@ -868,7 +872,11 @@ packages do not add gRPC as a hard dependency. C# output is one `.cs` file per schema, for example: -- `<csharp_out>/addressbook/addressbook.cs` +- `<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 @@ -916,7 +924,7 @@ public abstract partial record Animal ### Module Installation -Each schema generates a module owner that installs imported modules first and +Each schema generates a module class that installs imported modules first and then registers the local schema types: ```csharp @@ -931,12 +939,74 @@ public static class AddressbookForyModule } ``` -The C# module owner keeps the schema-file prefix even when several schemas share -the same C# namespace. +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 diff --git a/docs/compiler/index.md b/docs/compiler/index.md index e635bcde0b..99136fafb9 100644 --- a/docs/compiler/index.md +++ b/docs/compiler/index.md @@ -23,9 +23,9 @@ Fory IDL 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, C++, Go, Rust, JavaScript/TypeScript, C#, Swift, Dart, Scala, and Kotlin. Fory IDL can also -describe RPC services; for Java, Python, Go, Rust, Scala, and Kotlin, the compiler can -generate gRPC service companions that use Fory serialization for request and -response payloads. +describe RPC services; for Java, Python, Go, Rust, C#, Scala, and Kotlin, the +compiler can generate gRPC service companions that use Fory serialization for +request and response payloads. ## Example Schema @@ -88,16 +88,17 @@ service AnimalService { } ``` -Generate Java, Python, Rust, Scala, and Kotlin models plus gRPC service companions with: +Generate Java, Python, Rust, C#, Scala, and Kotlin models plus gRPC service companions with: ```bash -foryc animals.fdl --java_out=./generated/java --python_out=./generated/python --rust_out=./generated/rust --scala_out=./generated/scala --kotlin_out=./generated/kotlin --grpc +foryc animals.fdl --java_out=./generated/java --python_out=./generated/python --rust_out=./generated/rust --csharp_out=./generated/csharp --scala_out=./generated/scala --kotlin_out=./generated/kotlin --grpc ``` The generated service code uses normal gRPC APIs, but request and response objects are serialized with Fory. Applications provide their own grpc-java, -grpc-kotlin, `grpcio`, grpc-go, or Rust `tonic` and `bytes` dependencies; Fory -packages do not add gRPC as a hard dependency. +grpc-kotlin, `grpcio`, grpc-go, Rust `tonic` and `bytes`, or C# +`Grpc.Core.Api` and hosting/client dependencies; Fory packages do not add gRPC +as a hard dependency. ## Why Fory IDL? diff --git a/docs/compiler/protobuf-idl.md b/docs/compiler/protobuf-idl.md index acf7f7f5ad..40ad72b85c 100644 --- a/docs/compiler/protobuf-idl.md +++ b/docs/compiler/protobuf-idl.md @@ -41,19 +41,20 @@ how protobuf concepts map to Fory, and how to use protobuf-only Fory extension o ## Protobuf vs Fory at a Glance -| Aspect | Protocol Buffers | Fory | -| ------------------ | ----------------------------- | ------------------------------------------------ | -| Primary purpose | RPC/message contracts | High-performance object serialization | -| Encoding model | Tag-length-value | Fory binary protocol | -| Reference tracking | Not built-in | First-class (`ref`) | -| Circular refs | Not supported | Supported | -| Unknown fields | Preserved | Not preserved | -| Generated types | Protobuf-specific model types | Native language constructs | -| gRPC ecosystem | Native | Java/Python/Go/Rust/Scala/Kotlin service codegen | - -Fory can generate Java, Python, Go, Rust, Scala, and Kotlin gRPC service companions with -`--grpc`. Those services use normal gRPC transports but serialize request and -response payloads with Fory rather than protobuf. For broad gRPC ecosystem +| Aspect | Protocol Buffers | Fory | +| ------------------ | ----------------------------- | --------------------------------------------------- | +| Primary purpose | RPC/message contracts | High-performance object serialization | +| Encoding model | Tag-length-value | Fory binary protocol | +| Reference tracking | Not built-in | First-class (`ref`) | +| Circular refs | Not supported | Supported | +| Unknown fields | Preserved | Not preserved | +| Generated types | Protobuf-specific model types | Native language constructs | +| gRPC ecosystem | Native | Java/Python/Go/Rust/C#/Scala/Kotlin service codegen | + +Fory can generate Java, Python, Go, Rust, C#, Scala, and Kotlin gRPC service +companions with `--grpc`. Those services use normal gRPC transports but +serialize request and response payloads with Fory rather than protobuf. For +broad gRPC ecosystem tooling, schema reflection, and protobuf-native interceptors, protobuf remains the mature/default choice. @@ -314,17 +315,18 @@ languages. For supported service outputs, add `--grpc` to emit gRPC companion code: ```bash -foryc api.proto --java_out=./generated/java --python_out=./generated/python --rust_out=./generated/rust --scala_out=./generated/scala --kotlin_out=./generated/kotlin --grpc +foryc api.proto --java_out=./generated/java --python_out=./generated/python --rust_out=./generated/rust --csharp_out=./generated/csharp --scala_out=./generated/scala --kotlin_out=./generated/kotlin --grpc ``` Generated Java service files compile against grpc-java, generated Python service modules import `grpc`, generated Rust service files import `tonic` and `bytes`, -generated Scala service files compile against grpc-java, and generated Kotlin -service files compile against grpc-java and grpc-kotlin. -Add those dependencies in your application build; Fory packages do not add gRPC -as a hard dependency. Protobuf `oneof` fields are translated to Fory union -fields inside request and response messages. Direct union RPC request or -response types are not part of normal protobuf RPC syntax. +generated C# service files import `Grpc.Core.Api` types, generated Scala service +files compile against grpc-java, and generated Kotlin service files compile +against grpc-java and grpc-kotlin. Add those dependencies in your application +build; Fory packages do not add gRPC as a hard dependency. Protobuf `oneof` +fields are translated to Fory union fields inside request and response messages. +Direct union RPC request or response types are not part of normal protobuf RPC +syntax. ### Step 5: Run Compatibility Checks diff --git a/docs/compiler/schema-idl.md b/docs/compiler/schema-idl.md index 4fcf7c52f9..168c07ddcd 100644 --- a/docs/compiler/schema-idl.md +++ b/docs/compiler/schema-idl.md @@ -908,7 +908,7 @@ union_field := ['repeated'] field_type IDENTIFIER '=' INTEGER [field_options] '; Services define RPC method contracts in Fory IDL. They are optional: schemas with services still generate the normal data model types, and gRPC service code is generated only when the compiler is run with `--grpc` for supported language -outputs such as Java, Python, Go, Rust, Scala, and Kotlin. +outputs such as Java, Python, Go, Rust, C#, Scala, and Kotlin. ```protobuf message GetPetRequest [id=200] { @@ -950,8 +950,8 @@ service PetDirectory { of a service contract. - The generated gRPC companions use Fory serialization for each RPC payload. Applications that compile or run those companions provide their own gRPC - dependency, such as grpc-java, grpc-kotlin, `grpcio`, grpc-go, or Rust - `tonic` and `bytes`. + dependency, such as grpc-java, grpc-kotlin, `grpcio`, grpc-go, Rust `tonic` + and `bytes`, or C# `Grpc.Core.Api` plus a server or client package. **Grammar:** --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
