diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..7cd142405d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,140 @@ +# Apache Fory Site: System Understanding (Agent View) + +## 1. Project Positioning + +This repository contains the Apache Fory website and documentation site source (Docusaurus). +It is not the Fory core serialization library itself. + +Primary responsibilities: + +- Official homepage and marketing content (`src/pages` + custom components) +- Documentation (multi-version, multi-language) +- Blog +- Community, download, and related pages + +Core objective: stable static site publishing plus high-quality documentation and Chinese localization maintenance. + +## 2. Tech Stack and Runtime + +- Framework: Docusaurus 3 (React 18 + TypeScript) +- Styling and motion: CSS Modules, Tailwind (partial usage), AOS, Framer Motion +- Search: `docusaurus-lunr-search` +- Node requirement: `>=18` + +Common commands (`package.json`): + +- `npm run start` / `npm run start-en` / `npm run start-zh` +- `npm run build` (runs `prebuild` first) +- `npm run docusaurus docs:version ` (wrapped command with i18n version copy support) +- `npm run typecheck` + +## 3. Information Architecture and Directory Responsibilities + +Key directories: + +- `docs/`: current docs (current/dev) +- `versioned_docs/version-*/`: historical docs by version +- `versioned_sidebars/`: sidebars for versioned docs +- `i18n/zh-CN/docusaurus-plugin-content-docs/`: Chinese docs (`current` + `version-*`) +- `blog/`: blog content +- `src/pages/`: homepage, users page, download page, security page, etc. +- `src/theme/`: Docusaurus theme overrides (notably blog rendering behavior) +- `src/plugin/redirect.js`: site redirect logic +- `scripts/`: docs versioning and i18n helper scripts +- `.github/workflows/`: CI/CD pipelines + +Current docs footprint (rough file count): + +- `docs/`: 158 +- `versioned_docs/`: 333 +- `i18n/zh-CN/docusaurus-plugin-content-docs/`: 500 + +## 4. Docs Versioning Strategy + +- `versions.json` currently includes: `0.15, 0.14, 0.13, 0.12, 0.11, 0.10` +- In `docusaurus.config.ts`, `docs.lastVersion = "0.15"` +- The current docs label is `dev` (`current`) + +Recommended versioning entry point: + +- Use `npm run docusaurus docs:version ` +- This invokes `scripts/docusaurus-with-i18n.sh` +- After native Docusaurus versioning, the wrapper copies each locale’s `current/` to `version-/` + +## 5. Internationalization (i18n) Mechanism + +Enabled locales: + +- `en-US` (default) +- `zh-CN` + +Chinese docs paths: + +- `i18n/zh-CN/docusaurus-plugin-content-docs/current/` +- `i18n/zh-CN/docusaurus-plugin-content-docs/version-*/` + +Chinese top-level sidebar labels are managed in: + +- `i18n/zh-CN/docusaurus-plugin-content-docs/current.json` + +Prebuild step: + +- `scripts/copy-i18n-fallback.sh` +- It fills missing Chinese files for `specification` and `benchmarks` from English sources (`rsync --ignore-existing`) to prevent broken links + +This means Chinese docs may be a mix of translated content and English fallback files. + +## 6. Site Customization (vs. Default Docusaurus Behavior) + +- The homepage is composed of custom sections (Hero, Features, language cards, code carousel) +- `src/plugin/redirect.js` has built-in redirects: + - `fury.apache.org` -> `fory.apache.org` + - Old routes `/docs/.../docs/{guide|introduction|start}` -> cleaned routes +- Blog theme overrides: + - List pages prefer frontmatter `description` as summary + - Post detail pages remove the global blog sidebar for a focused reading layout + +## 7. CI/CD and Quality Gates + +### CI + +- `lint.yml` + - Markdown lint (`markdownlint-cli`) + - YAML lint (`yamllint`) +- `link-check.yml` + - Workflow exists, but link-check steps are currently commented out (not effectively running) + +### CD + +- `deploy.yml` + - Runs on push to `main` and on pull requests + - Calls `scripts/unified-docs/script.py` + - Runs `npm run download-avatars` + `npm run build` + - Publishes to `deploy` branch for non-PR events (`peaceiris/actions-gh-pages`) + +## 8. Key Repository Caveats + +- `CONTRIBUTING.md` states that `docs/guide` and `docs/specification` are mainly synced from `apache/fory`. + For those sections, confirm whether changes should go to the main `apache/fory` repo instead. +- `scripts/unified-docs/script.py` uses `i18n/eu-US/...` paths (not `en-US`); treat this as existing behavior and validate intent before changing. +- Since link-check is not effectively active, external link regressions may pass PR checks. +- The repo has substantial versioned/mirrored docs; avoid accidental bulk edits in `versioned_docs` and `i18n/version-*`. + +## 9. Recommended Agent Workflow + +- Before editing docs, scope the target explicitly: + - `docs/current` + - `versioned_docs/version-*` + - `i18n/zh-CN/current` + - `i18n/zh-CN/version-*` +- For Chinese translation tasks: + - Follow `skills/translate-docs-zh/SKILL.md` + - Use terminology from `skills/translate-docs-zh/references/terminology.md` + - Do not use external translation tools/APIs/websites +- When changing top-level sidebar categories (Introduction/Start/Schema IDL & Compiler/Guide): + - Update `sidebars.ts` + - Update `i18n/zh-CN/docusaurus-plugin-content-docs/current.json` (and version JSON files if needed) +- Minimum pre-commit validation: + - `npm run build` + - `npm run typecheck` + - Manually verify critical routes: `/`, `/docs`, `/zh-CN/docs`, `/blog` diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current.json b/i18n/zh-CN/docusaurus-plugin-content-docs/current.json index a3936023b9..ac5312509b 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current.json +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current.json @@ -2,5 +2,21 @@ "version.label": { "message": "dev", "description": "The label for version current" + }, + "sidebar.docsSidebar.category.Introduction": { + "message": "Apache Fory 介绍", + "description": "The label for category Introduction in sidebar docsSidebar" + }, + "sidebar.docsSidebar.category.Start": { + "message": "快速开始", + "description": "The label for category Start in sidebar docsSidebar" + }, + "sidebar.docsSidebar.category.Schema IDL & Compiler": { + "message": "Schema IDL 与编译器", + "description": "The label for category Schema IDL & Compiler in sidebar docsSidebar" + }, + "sidebar.docsSidebar.category.Guide": { + "message": "用户指南", + "description": "The label for category Guide in sidebar docsSidebar" } } diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/benchmarks/go/benchmark_report.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/benchmarks/go/benchmark_report.md index a1c3d635f2..f73aacf0a2 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/benchmarks/go/benchmark_report.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/benchmarks/go/benchmark_report.md @@ -10,48 +10,48 @@ ## 性能摘要 -| 数据类型 | 操作 | Fory (ops/s) | Protobuf (ops/s) | Msgpack (ops/s) | Fory vs PB | Fory vs MP | -|---------|------|--------------|------------------|-----------------|------------|------------| -| Struct | 序列化 | 15.16M | 10.23M | 5.41M | 1.48x | 2.80x | -| Struct | 反序列化 | 12.10M | 11.01M | 3.23M | 1.10x | 3.75x | -| Structlist | 序列化 | 1.58M | 561K | 299K | 2.82x | 5.28x | -| Structlist | 反序列化 | 1.10M | 529K | 175K | 2.09x | 6.30x | -| Sample | 序列化 | 7.28M | 2.72M | 670K | 2.68x | 10.87x | -| Sample | 反序列化 | 3.79M | 2.37M | 376K | 1.60x | 10.09x | -| Samplelist | 序列化 | 510K | 141K | 38K | 3.61x | 13.34x | -| Samplelist | 反序列化 | 236K | 107K | 19K | 2.20x | 12.66x | -| Mediacontent | 序列化 | 3.72M | 2.12M | 1.29M | 1.75x | 2.88x | -| Mediacontent | 反序列化 | 2.34M | 1.81M | 698K | 1.30x | 3.35x | -| Mediacontentlist | 序列化 | 268K | 110K | 72K | 2.44x | 3.72x | -| Mediacontentlist | 反序列化 | 138K | 87K | 36K | 1.58x | 3.86x | +| 数据类型 | 操作 | Fory (ops/s) | Protobuf (ops/s) | Msgpack (ops/s) | Fory vs PB | Fory vs MP | +| ---------------- | -------- | ------------ | ---------------- | --------------- | ---------- | ---------- | +| Struct | 序列化 | 15.16M | 10.23M | 5.41M | 1.48x | 2.80x | +| Struct | 反序列化 | 12.10M | 11.01M | 3.23M | 1.10x | 3.75x | +| Structlist | 序列化 | 1.58M | 561K | 299K | 2.82x | 5.28x | +| Structlist | 反序列化 | 1.10M | 529K | 175K | 2.09x | 6.30x | +| Sample | 序列化 | 7.28M | 2.72M | 670K | 2.68x | 10.87x | +| Sample | 反序列化 | 3.79M | 2.37M | 376K | 1.60x | 10.09x | +| Samplelist | 序列化 | 510K | 141K | 38K | 3.61x | 13.34x | +| Samplelist | 反序列化 | 236K | 107K | 19K | 2.20x | 12.66x | +| Mediacontent | 序列化 | 3.72M | 2.12M | 1.29M | 1.75x | 2.88x | +| Mediacontent | 反序列化 | 2.34M | 1.81M | 698K | 1.30x | 3.35x | +| Mediacontentlist | 序列化 | 268K | 110K | 72K | 2.44x | 3.72x | +| Mediacontentlist | 反序列化 | 138K | 87K | 36K | 1.58x | 3.86x | ## 详细耗时(ns/op) -| 数据类型 | 操作 | Fory | Protobuf | Msgpack | -|---------|------|------|----------|---------| -| Struct | 序列化 | 66.0 | 97.8 | 184.9 | -| Struct | 反序列化 | 82.7 | 90.9 | 309.6 | -| Structlist | 序列化 | 632.8 | 1783.0 | 3340.0 | -| Structlist | 反序列化 | 906.4 | 1891.0 | 5709.0 | -| Sample | 序列化 | 137.3 | 367.3 | 1492.0 | -| Sample | 反序列化 | 263.6 | 422.2 | 2661.0 | -| Samplelist | 序列化 | 1962.0 | 7087.0 | 26169.0 | -| Samplelist | 反序列化 | 4234.0 | 9321.0 | 53615.0 | -| Mediacontent | 序列化 | 268.8 | 471.1 | 773.7 | -| Mediacontent | 反序列化 | 426.9 | 553.1 | 1432.0 | -| Mediacontentlist | 序列化 | 3736.0 | 9107.0 | 13911.0 | -| Mediacontentlist | 反序列化 | 7247.0 | 11435.0 | 27975.0 | +| 数据类型 | 操作 | Fory | Protobuf | Msgpack | +| ---------------- | -------- | ------ | -------- | ------- | +| Struct | 序列化 | 66.0 | 97.8 | 184.9 | +| Struct | 反序列化 | 82.7 | 90.9 | 309.6 | +| Structlist | 序列化 | 632.8 | 1783.0 | 3340.0 | +| Structlist | 反序列化 | 906.4 | 1891.0 | 5709.0 | +| Sample | 序列化 | 137.3 | 367.3 | 1492.0 | +| Sample | 反序列化 | 263.6 | 422.2 | 2661.0 | +| Samplelist | 序列化 | 1962.0 | 7087.0 | 26169.0 | +| Samplelist | 反序列化 | 4234.0 | 9321.0 | 53615.0 | +| Mediacontent | 序列化 | 268.8 | 471.1 | 773.7 | +| Mediacontent | 反序列化 | 426.9 | 553.1 | 1432.0 | +| Mediacontentlist | 序列化 | 3736.0 | 9107.0 | 13911.0 | +| Mediacontentlist | 反序列化 | 7247.0 | 11435.0 | 27975.0 | ### 序列化后数据大小(字节) -| 数据类型 | Fory | Protobuf | Msgpack | -|---------|------|----------|---------| -| Struct | 58 | 61 | 57 | -| Sample | 446 | 375 | 524 | -| MediaContent | 342 | 301 | 400 | -| StructList | 560 | 1260 | 1146 | -| SampleList | 7600 | 7560 | 10486 | -| MediaContentList | 5776 | 6080 | 8006 | +| 数据类型 | Fory | Protobuf | Msgpack | +| ---------------- | ---- | -------- | ------- | +| Struct | 58 | 61 | 57 | +| Sample | 446 | 375 | 524 | +| MediaContent | 342 | 301 | 400 | +| StructList | 560 | 1260 | 1146 | +| SampleList | 7600 | 7560 | 10486 | +| MediaContentList | 5776 | 6080 | 8006 | ## 性能图表 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/_category_.json b/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/_category_.json new file mode 100644 index 0000000000..abf19e9fcb --- /dev/null +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 3, + "label": "Schema IDL 与编译器", + "collapsible": true, + "collapsed": true +} diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/compiler-guide.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/compiler-guide.md index 1c8184bfda..0046cbcd3b 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/compiler-guide.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/compiler-guide.md @@ -19,9 +19,7 @@ license: | limitations under the License. --- -> 中文导读:本文档为 Fory 编译器/协议规范文档的中文译稿。为避免改变规范语义,代码片段、类型名、协议字段名保持英文,说明性文字优先翻译为中文。 - -本指南介绍 Fory IDL 编译器的安装、使用与集成。 +本指南介绍 Fory IDL 编译器的安装、命令行使用方式以及构建系统集成方案。 ## 安装 @@ -52,155 +50,153 @@ foryc --scan-generated [OPTIONS] ### 选项 -Compile options: - -| Option | Description | Default | -| ------------------------------------- | ----------------------------------------------------- | ------------------- | -| `--lang` | Comma-separated target languages | `all` | -| `--output`, `-o` | Output directory | `./generated` | -| `--package` | Override package name from Fory IDL file | (from file) | -| `-I`, `--proto_path`, `--import_path` | Add directory to import search path (can be repeated) | (none) | -| `--java_out=DST_DIR` | Generate Java code in DST_DIR | (none) | -| `--python_out=DST_DIR` | Generate Python code in DST_DIR | (none) | -| `--cpp_out=DST_DIR` | Generate C++ code in DST_DIR | (none) | -| `--go_out=DST_DIR` | Generate Go code in DST_DIR | (none) | -| `--rust_out=DST_DIR` | Generate Rust code in DST_DIR | (none) | -| `--go_nested_type_style` | Go nested type naming: `camelcase` or `underscore` | from schema/default | -| `--emit-fdl` | Print translated Fory IDL for non-`.fdl` inputs | `false` | -| `--emit-fdl-path` | Write translated Fory IDL to a file or directory | (stdout) | - -Scan options (with `--scan-generated`): - -| Option | Description | Default | -| ------------ | ------------------------------ | ------- | -| `--root` | Root directory to scan | `.` | -| `--relative` | Print paths relative to root | `false` | -| `--delete` | Delete matched generated files | `false` | -| `--dry-run` | Scan/print only, do not delete | `false` | - -### Scan Generated Files - -Use `--scan-generated` to find files produced by `foryc`. The scanner walks -the tree recursively, skips `build/`, `target/`, and hidden directories, and prints -each generated file as it is found. +编译选项: + +| 选项 | 说明 | 默认值 | +| ------------------------------------- | ------------------------------------------------ | ------------- | +| `--lang` | 目标语言列表(逗号分隔) | `all` | +| `--output`, `-o` | 输出目录 | `./generated` | +| `--package` | 覆盖 Fory IDL 文件中的 package | (来自文件) | +| `-I`, `--proto_path`, `--import_path` | 添加 import 搜索路径(可重复) | (无) | +| `--java_out=DST_DIR` | 将 Java 代码输出到 `DST_DIR` | (无) | +| `--python_out=DST_DIR` | 将 Python 代码输出到 `DST_DIR` | (无) | +| `--cpp_out=DST_DIR` | 将 C++ 代码输出到 `DST_DIR` | (无) | +| `--go_out=DST_DIR` | 将 Go 代码输出到 `DST_DIR` | (无) | +| `--rust_out=DST_DIR` | 将 Rust 代码输出到 `DST_DIR` | (无) | +| `--go_nested_type_style` | Go 嵌套类型命名风格:`camelcase` 或 `underscore` | schema/默认值 | +| `--emit-fdl` | 对非 `.fdl` 输入打印转换后的 Fory IDL | `false` | +| `--emit-fdl-path` | 将转换后的 Fory IDL 写入文件或目录 | (stdout) | + +扫描选项(配合 `--scan-generated`): + +| 选项 | 说明 | 默认值 | +| ------------ | ---------------------- | ------- | +| `--root` | 扫描根目录 | `.` | +| `--relative` | 以相对路径输出 | `false` | +| `--delete` | 删除匹配到的生成文件 | `false` | +| `--dry-run` | 仅扫描输出,不执行删除 | `false` | + +### 扫描生成文件 + +使用 `--scan-generated` 可以定位 `foryc` 生成的文件。扫描器会递归遍历目录树,跳过 `build/`、`target/` 和隐藏目录,并输出找到的每个生成文件。 ```bash -# Scan current directory +# 扫描当前目录 foryc --scan-generated -# Scan a specific root +# 扫描指定根目录 foryc --scan-generated --root ./src -# Print paths relative to the scan root +# 输出相对路径 foryc --scan-generated --root ./src --relative -# Delete scanned generated files +# 删除扫描到的生成文件 foryc --scan-generated --root ./src --delete -# Dry-run (scan and print only) +# Dry-run(仅扫描与输出) foryc --scan-generated --root ./src --dry-run ``` -### Examples +### 示例 -**Compile for all languages:** +**为所有语言编译:** ```bash foryc schema.fdl ``` -**Compile for specific languages:** +**为指定语言编译:** ```bash foryc schema.fdl --lang java,python ``` -**Specify output directory:** +**指定输出目录:** ```bash foryc schema.fdl --output ./src/generated ``` -**Override package name:** +**覆盖 package:** ```bash foryc schema.fdl --package com.myapp.models ``` -**Compile multiple files:** +**编译多个文件:** ```bash foryc user.fdl order.fdl product.fdl --output ./generated ``` -**Use import search paths:** +**使用 import 搜索路径:** ```bash -# Add a single import path +# 单个路径 foryc src/main.fdl -I libs/common -# Add multiple import paths (repeated option) +# 多个路径(重复参数) foryc src/main.fdl -I libs/common -I libs/types -# Add multiple import paths (comma-separated) +# 多个路径(逗号分隔) foryc src/main.fdl -I libs/common,libs/types,third_party/ -# Using --proto_path (protoc-compatible alias) +# --proto_path(protoc 兼容别名) foryc src/main.fdl --proto_path=libs/common -# Mix all styles +# 混合写法 foryc src/main.fdl -I libs/common,libs/types --proto_path third_party/ ``` -**Language-specific output directories (protoc-style):** +**语言定向输出目录(protoc 风格):** ```bash -# Generate only Java code to a specific directory +# 仅生成 Java foryc schema.fdl --java_out=./src/main/java -# Generate multiple languages to different directories +# 多语言分别输出到不同目录 foryc schema.fdl --java_out=./java/gen --python_out=./python/src --go_out=./go/gen -# Combine with import paths +# 结合 import 路径 foryc schema.fdl --java_out=./gen/java -I proto/ -I common/ ``` -When using `--{lang}_out` options: +使用 `--{lang}_out` 时: -- Only the specified languages are generated (not all languages) -- The compiler writes under the specified directory (language-specific generators may still create package/module subdirectories) -- This is compatible with protoc-style workflows +- 只生成显式指定的语言(不会生成全部语言) +- 输出写入指定目录(语言生成器可能继续按包/模块分层) +- 兼容 protoc 风格工作流 -**Inspect translated Fory IDL from proto/fbs input:** +**查看 proto/fbs 输入转换后的 Fory IDL:** ```bash -# Print translated Fory IDL to stdout +# 输出到 stdout foryc schema.proto --emit-fdl -# Write translated Fory IDL to a directory +# 输出到目录 foryc schema.fbs --emit-fdl --emit-fdl-path ./translated ``` -## Import Path Resolution +## Import 路径解析 -When compiling Fory IDL files with imports, the compiler searches for imported files in this order: +编译含 import 的 Fory IDL 文件时,导入文件按以下顺序查找: -1. **Relative to the importing file (default)** - The directory containing the file with the import statement is always searched first, automatically. No `-I` flag needed for same-directory imports. -2. **Each `-I` path in order** - Additional search paths specified on the command line +1. **相对于导入者文件目录(默认)**:始终优先查找,无需 `-I` +2. **按顺序遍历每个 `-I` 路径** -**Same-directory imports work automatically:** +**同目录 import 可直接生效:** ```protobuf // main.fdl -import "common.fdl"; // Found if common.fdl is in the same directory +import "common.fdl"; // 若 common.fdl 在同目录,将自动找到 ``` ```bash -# No -I needed for same-directory imports +# 同目录导入无需 -I foryc main.fdl ``` -**Example project structure:** +**示例目录结构:** ``` project/ @@ -210,7 +206,7 @@ project/ └── common.fdl ``` -**Without `-I` (fails):** +**不加 `-I`(失败):** ```bash $ foryc src/main.fdl @@ -218,7 +214,7 @@ Import error: Import not found: common.fdl Searched in: /project/src ``` -**With `-I` (succeeds):** +**加 `-I`(成功):** ```bash $ foryc src/main.fdl -I libs/ @@ -226,17 +222,17 @@ Compiling src/main.fdl... Resolved 1 import(s) ``` -## Supported Languages +## 支持语言 -| Language | Flag | Output Extension | Description | -| -------- | -------- | ---------------- | --------------------------- | -| Java | `java` | `.java` | POJOs with Fory annotations | -| Python | `python` | `.py` | Dataclasses with type hints | -| Go | `go` | `.go` | Structs with struct tags | -| Rust | `rust` | `.rs` | Structs with derive macros | -| C++ | `cpp` | `.h` | Structs with FORY macros | +| 语言 | 标记 | 输出后缀 | 说明 | +| ------ | -------- | -------- | ---------------------- | +| Java | `java` | `.java` | 带 Fory 注解的 POJO | +| Python | `python` | `.py` | 带类型提示的 dataclass | +| Go | `go` | `.go` | 带 struct tag 的结构体 | +| Rust | `rust` | `.rs` | 带 derive 宏的结构体 | +| C++ | `cpp` | `.h` | 带 FORY 宏的结构体 | -## Output Structure +## 输出结构 ### Java @@ -251,9 +247,9 @@ generated/ └── ExampleForyRegistration.java ``` -- One file per type (enum or message) -- Package structure matches Fory IDL package -- Registration helper class generated +- 每个类型(enum/message)单独一个文件 +- 包路径与 Fory IDL package 一致 +- 会生成注册辅助类 ### Python @@ -263,9 +259,9 @@ generated/ └── example.py ``` -- Single module with all types -- Module name derived from package -- Registration function included +- 所有类型位于单模块 +- 模块名由 package 派生 +- 包含注册函数 ### Go @@ -276,9 +272,9 @@ generated/ └── example.go ``` -- Single file with all types -- Directory and package name are derived from `go_package` or the Fory IDL package -- Registration function included +- 所有类型在单文件中 +- 目录名与包名来自 `go_package` 或 Fory IDL package +- 包含注册函数 ### Rust @@ -288,9 +284,9 @@ generated/ └── example.rs ``` -- Single module with all types -- Module name derived from package -- Registration function included +- 所有类型位于单模块 +- 模块名由 package 派生 +- 包含注册函数 ### C++ @@ -300,15 +296,15 @@ generated/ └── example.h ``` -- Single header file -- Namespace matches package (dots to `::`) -- Header guards and forward declarations +- 单头文件输出 +- 命名空间与 package 对齐(点号转换为 `::`) +- 自动包含 header guard 与前向声明 -## Build Integration +## 构建系统集成 ### Maven (Java) -Add to your `pom.xml`: +在 `pom.xml` 中添加: ```xml @@ -339,7 +335,7 @@ Add to your `pom.xml`: ``` -Add generated sources: +添加生成源码目录: ```xml @@ -368,7 +364,7 @@ Add generated sources: ### Gradle (Java/Kotlin) -Add to `build.gradle`: +在 `build.gradle` 中添加: ```groovy task generateForyTypes(type: Exec) { @@ -390,7 +386,7 @@ sourceSets { ### Python (setuptools) -Add to `setup.py` or `pyproject.toml`: +在 `setup.py` 或 `pyproject.toml` 中加入生成步骤: ```python # setup.py @@ -413,24 +409,24 @@ setup( ) ``` -### Go (go generate) +### Go (`go generate`) -Add to your Go file: +在 Go 文件中添加: ```go //go:generate foryc ../schema.fdl --lang go --output . package models ``` -Run: +执行: ```bash go generate ./... ``` -### Rust (build.rs) +### Rust (`build.rs`) -Add to `build.rs`: +在 `build.rs` 中添加: ```rust use std::process::Command; @@ -451,7 +447,7 @@ fn main() { ### CMake (C++) -Add to `CMakeLists.txt`: +在 `CMakeLists.txt` 中添加: ```cmake find_program(FORY_COMPILER foryc) @@ -474,7 +470,7 @@ target_include_directories(mylib PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/generated) ### Bazel -Create a rule in `BUILD`: +在 `BUILD` 中添加规则: ```python genrule( @@ -492,51 +488,51 @@ cc_library( ) ``` -## Error Handling +## 错误处理 -### Syntax Errors +### 语法错误 ``` Error: Line 5, Column 12: Expected ';' after field declaration ``` -Fix: Check the indicated line for missing semicolons or syntax issues. +修复方式:检查对应行是否缺少分号或存在语法问题。 -### Duplicate Type Names +### 类型名重复 ``` Error: Duplicate type name: User ``` -Fix: Ensure each enum and message has a unique name within the file. +修复方式:确保同一文件内每个 enum/message 名称唯一。 -### Duplicate Type IDs +### 类型 ID 重复 ``` Error: Duplicate type ID 100: User and Order ``` -Fix: Assign unique type IDs to each type. +修复方式:为每个类型分配唯一 ID。 -### Unknown Type References +### 未知类型引用 ``` Error: Unknown type 'Address' in Customer.address ``` -Fix: Define the referenced type before using it, or check for typos. +修复方式:先定义被引用类型,或检查类型名拼写。 -### Duplicate Field Numbers +### 字段号重复 ``` Error: Duplicate field number 1 in User: name and id ``` -Fix: Assign unique field numbers within each message. +修复方式:确保同一 message 内字段号唯一。 -## Best Practices +## 最佳实践 -### Project Structure +### 项目结构 ``` project/ @@ -549,12 +545,12 @@ project/ └── build.gradle ``` -### Version Control +### 版本控制 -- **Track**: Fory IDL schema files -- **Ignore**: Generated code (can be regenerated) +- **纳入版本控制**:Fory IDL schema 文件 +- **忽略生成代码**:可在构建时再生成 -Add to `.gitignore`: +在 `.gitignore` 中加入: ``` # Generated Fory IDL code @@ -562,12 +558,12 @@ src/generated/ generated/ ``` -### CI/CD Integration +### CI/CD 集成 -Always regenerate during builds: +在构建流程中始终重新生成代码: ```yaml -# GitHub Actions example +# GitHub Actions 示例 steps: - name: Install Fory IDL Compiler run: pip install ./compiler @@ -579,14 +575,14 @@ steps: run: ./gradlew build ``` -### Schema Evolution +### Schema 演进 -When modifying schemas: +修改 schema 时建议遵循: -1. **Never reuse field numbers** - Mark as reserved instead -2. **Never change type IDs** - They're part of the binary format -3. **Add new fields** - Use new field numbers -4. **Use `optional`** - For backward compatibility +1. **不要复用字段号**:删除字段后应保留/预留 +2. **不要改动类型 ID**:类型 ID 属于二进制协议的一部分 +3. **新增字段使用新字段号** +4. **优先使用 `optional`**:保持向后兼容 ```protobuf message User [id=100] { @@ -597,7 +593,7 @@ message User [id=100] { } ``` -## Troubleshooting +## 故障排查 ### Command Not Found @@ -605,7 +601,7 @@ message User [id=100] { foryc: command not found ``` -**Solution:** Ensure the compiler is installed and in your PATH: +**解决:** 确认编译器已安装且在 PATH 中: ```bash pip install -e ./compiler @@ -619,15 +615,15 @@ export PATH=$PATH:~/.local/bin Permission denied: ./generated ``` -**Solution:** Ensure write permissions on the output directory: +**解决:** 确保输出目录具备写权限: ```bash chmod -R u+w ./generated ``` -### Import Errors in Generated Code +### 生成代码 import 错误 -**Java:** Ensure Fory dependency is in your project: +**Java:** 确保项目包含 Fory 依赖: ```xml @@ -637,23 +633,23 @@ chmod -R u+w ./generated ``` -**Python:** Ensure pyfory is installed: +**Python:** 确保安装 `pyfory`: ```bash pip install pyfory ``` -**Go:** Ensure fory module is available: +**Go:** 确保可获取 fory 模块: ```bash go get github.com/apache/fory/go/fory ``` -**Rust:** Ensure fory crate is in `Cargo.toml`: +**Rust:** 确保 `Cargo.toml` 中包含 fory crate: ```toml [dependencies] fory = "x.y.z" ``` -**C++:** Ensure Fory headers are in include path. +**C++:** 确保编译器 include 路径可找到 Fory 头文件。 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/flatbuffers-idl.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/flatbuffers-idl.md index 579ac6c3fc..6a2bfd2885 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/flatbuffers-idl.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/flatbuffers-idl.md @@ -19,59 +19,49 @@ license: | limitations under the License. --- -> 中文导读:本文档为 Fory 编译器/协议规范文档的中文译稿。为避免改变规范语义,代码片段、类型名、协议字段名保持英文,说明性文字优先翻译为中文。 - 本页说明 Apache Fory 如何读取 FlatBuffers schema(`.fbs`)并将其转换为 Fory IR 以生成代码。 ## 本页内容 -- When to use FlatBuffers input with Fory -- Exact FlatBuffers to Fory mapping behavior -- Supported Fory-specific attributes in `.fbs` -- Migration notes and generated-code differences +- 何时应在 Fory 中使用 FlatBuffers 输入 +- FlatBuffers 到 Fory 的精确映射行为 +- `.fbs` 中支持的 Fory 扩展属性 +- 迁移注意事项与生成代码差异 ## 为什么使用 Apache Fory -- Idiomatic generated code: Fory generates language-idiomatic classes/structs - that can be used directly as domain objects. -- Java performance: In Java object-serialization workloads, Fory is faster than - FlatBuffers in Fory benchmarks. -- Other languages: serialization performance is generally in a similar range. -- Deserialization in practice: FlatBuffers does not perform native-object deserialization and is - faster by default, but if your application needs native objects, it requires - conversion and that conversion step can dominate read cost. In those cases, - Fory deserialization is often faster end-to-end. -- Easier APIs: Fory uses direct native objects, so you do not need to - reverse-build tables or manually manage offsets. -- Better graph modeling: Shared and circular references are first-class features - in Fory. +- **生成代码更符合语言习惯**:Fory 会生成各语言常用风格的类/结构体,可直接作为领域对象使用。 +- **Java 性能更优**:在 Fory 的 Java 对象序列化基准中,Fory 通常快于 FlatBuffers。 +- **其他语言性能相近**:序列化性能通常处于同一量级。 +- **实际反序列化链路更高效**:FlatBuffers 默认并不做原生对象反序列化,因此看起来更快;但当业务需要原生对象时,还需额外转换,这一步往往成为主要开销。在这种场景下,Fory 端到端反序列化通常更快。 +- **API 更简单**:Fory 直接操作原生对象,无需反向构建 table 或手动管理 offset。 +- **对象图建模能力更强**:Fory 原生支持共享引用和循环引用。 ## 快速决策指南 -| Situation | Recommended Path | -| ------------------------------------------------------------------ | ---------------------- | -| You already have `.fbs` schemas and want Fory runtime/codegen | Use FlatBuffers input | -| You are starting new schema work and want full Fory syntax control | Use native Fory IDL | -| You need FlatBuffers wire compatibility at runtime | Keep FlatBuffers stack | -| You need Fory object-graph semantics (`ref`, weak refs, etc.) | Use Fory | +| 场景 | 建议路径 | +| ----------------------------------------------- | ----------------------- | +| 已有 `.fbs` schema,想接入 Fory 运行时/代码生成 | 使用 FlatBuffers 输入 | +| 新建 schema,希望完整使用 Fory 语法能力 | 使用原生 Fory IDL | +| 运行时必须保持 FlatBuffers 线格式兼容 | 继续使用 FlatBuffers 栈 | +| 需要 Fory 对象图语义(`ref`、弱引用等) | 使用 Fory | ## FlatBuffers 到 Fory 的映射 -### Schema-Level Rules +### Schema 级规则 -- `namespace` maps to Fory package namespace. -- `include` entries map to Fory imports. -- `table` is translated as `evolving=true`. -- `struct` is translated as `evolving=false`. -- `root_type` is parsed but ignored by Fory runtime/codegen. -- `file_identifier` and `file_extension` are parsed but not used by Fory codegen. +- `namespace` 映射为 Fory package 命名空间。 +- `include` 映射为 Fory import。 +- `table` 会被翻译为 `evolving=true`。 +- `struct` 会被翻译为 `evolving=false`。 +- `root_type` 会被解析,但 Fory 运行时/代码生成不会使用。 +- `file_identifier` 与 `file_extension` 会被解析,但 Fory 代码生成不会使用。 -### Field Numbering +### 字段编号 -FlatBuffers fields do not have explicit field IDs. Fory assigns field numbers by -source declaration order, starting at `1`. +FlatBuffers 字段没有显式 field ID。Fory 会按源码声明顺序分配字段号,从 `1` 开始。 -### Scalar Type Mapping +### 标量类型映射 | FlatBuffers | Fory Type | | ----------- | --------- | @@ -88,14 +78,14 @@ source declaration order, starting at `1`. | `bool` | `bool` | | `string` | `string` | -Vectors (`[T]`) map to Fory lists. +向量(`[T]`)映射为 Fory 列表类型。 -### Unions +### 联合类型 -FlatBuffers unions map to Fory unions. +FlatBuffers union 映射为 Fory union。 -- Case IDs are assigned by declaration order, starting at `1`. -- Case names are derived from type names using snake_case field naming. +- case ID 按声明顺序分配,从 `1` 开始。 +- case 名称由类型名转换为 snake_case 字段名。 **FlatBuffers** @@ -110,7 +100,7 @@ table Container { } ``` -**Fory shape after translation** +**转换后的 Fory 结构** ```protobuf union Payload { @@ -123,33 +113,31 @@ message Container { } ``` -### Defaults and Metadata +### 默认值与元数据 -- FlatBuffers default values are parsed but not applied as Fory runtime defaults. -- Non-Fory metadata attributes are preserved as generic options in IR and may be - consumed by downstream tooling. +- FlatBuffers 默认值会被解析,但不会作为 Fory 运行时默认值生效。 +- 非 Fory 的 metadata 属性会作为通用 option 保留在 IR 中,供下游工具按需消费。 -## Fory-Specific Attributes in FlatBuffers +## FlatBuffers 中的 Fory 扩展属性 -FlatBuffers metadata attributes use `key:value`. For Fory-specific options, use -`fory_` (or `fory.`) prefix in `.fbs`; the prefix is removed during parsing. +FlatBuffers metadata 属性写法为 `key:value`。对于 Fory 扩展选项,在 `.fbs` 中使用 `fory_`(或 `fory.`)前缀;解析时会去掉该前缀。 -### Supported Field Attributes +### 支持的字段属性 -| FlatBuffers Attribute | Effect in Fory | -| -------------------------------- | ----------------------------------------------------- | -| `fory_ref:true` | Enable reference tracking for the field | -| `fory_nullable:true` | Mark field optional/nullable | -| `fory_weak_ref:true` | Enable weak reference semantics and implies `ref` | -| `fory_thread_safe_pointer:false` | For ref fields, select non-thread-safe pointer flavor | +| FlatBuffers Attribute | 在 Fory 中的效果 | +| -------------------------------- | --------------------------------- | +| `fory_ref:true` | 为字段启用引用跟踪 | +| `fory_nullable:true` | 将字段标记为 optional/nullable | +| `fory_weak_ref:true` | 启用弱引用语义,并隐含开启 `ref` | +| `fory_thread_safe_pointer:false` | 对 ref 字段选择非线程安全指针类型 | -Semantics: +语义说明: -- `fory_weak_ref:true` implies `ref`. -- `fory_thread_safe_pointer` only takes effect when the field is ref-tracked. -- For list fields, `fory_ref:true` applies to list elements. +- `fory_weak_ref:true` 隐含 `ref`。 +- `fory_thread_safe_pointer` 仅在字段启用 ref 跟踪时生效。 +- 对列表字段,`fory_ref:true` 作用于列表元素。 -Example: +示例: ```fbs table Node { @@ -159,42 +147,37 @@ table Node { } ``` -## Generated Code Differences +## 生成代码差异 -Using `.fbs` as input to Fory still produces normal Fory-generated code, not -FlatBuffers `ByteBuffer`-style APIs. +即使用 `.fbs` 作为 Fory 输入,生成的依然是标准 Fory 代码,而不是 FlatBuffers 的 `ByteBuffer` 风格 API。 -- Java: POJOs/records with Fory metadata -- Python: dataclasses plus registration helpers -- Go/Rust/C++: native structs and Fory metadata +- Java:带 Fory 元数据的 POJO/record +- Python:dataclass 与注册辅助代码 +- Go/Rust/C++:原生结构体与 Fory 元数据 -The serialization format is Fory binary protocol, not FlatBuffers wire format. +最终序列化格式是 Fory 二进制协议,而不是 FlatBuffers 线格式。 -## Usage +## 用法 -Compile a FlatBuffers schema directly: +直接编译 FlatBuffers schema: ```bash foryc schema.fbs --lang java,python --output ./generated ``` -Inspect translated schema syntax for debugging: +输出转换后的 Fory schema 语法以便调试: ```bash foryc schema.fbs --emit-fdl --emit-fdl-path ./translated ``` -## Migration Notes +## 迁移注意事项 -1. Keep existing `namespace` values stable to keep type registration stable. -2. Review fields that relied on FlatBuffers default literals and set explicit - defaults in application code if needed. -3. Add `fory_ref`/`fory_weak_ref` where object-graph semantics are required. -4. Validate generated model behavior with roundtrip tests before replacing - existing serialization paths. +1. 保持现有 `namespace` 稳定,以保证类型注册稳定。 +2. 检查依赖 FlatBuffers 字面量默认值的字段,并在业务代码中补充显式默认值。 +3. 在需要对象图语义的字段上添加 `fory_ref`/`fory_weak_ref`。 +4. 替换现有序列化路径前,先用 roundtrip 测试验证生成模型行为。 -## Summary +## 总结 -FlatBuffers input lets you reuse existing `.fbs` schemas while moving to Fory's -runtime and code generation model. This is useful for incremental migration, -while preserving schema investment and adopting Fory-native object APIs. +FlatBuffers 输入模式可让你复用现有 `.fbs` schema,同时迁移到 Fory 运行时与代码生成模型。它适合渐进式迁移场景:既保留既有 schema 投入,又能采用 Fory 原生对象 API。 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/generated-code.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/generated-code.md index ce33bac1e9..cadf241ab8 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/generated-code.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/generated-code.md @@ -19,20 +19,18 @@ license: | limitations under the License. --- -> 中文导读:本文档为 Fory 编译器/协议规范文档的中文译稿。为避免改变规范语义,代码片段、类型名、协议字段名保持英文,说明性文字优先翻译为中文。 +本文档说明各目标语言的代码生成结果与结构。 -本文档说明各目标语言的生成代码结构。 +Fory IDL 生成的类型遵循宿主语言习惯,可直接作为领域对象使用。生成代码同时包含 `to/from bytes` 辅助方法和类型注册辅助逻辑。 -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 registration helpers. +## 参考 Schema -## Reference Schemas +下面示例基于两个真实 schema: -The examples below use two real schemas: +1. `addressbook.fdl`(显式类型 ID) +2. `auto_id.fdl`(未显式声明类型 ID) -1. `addressbook.fdl` (explicit type IDs) -2. `auto_id.fdl` (no explicit type IDs) - -### `addressbook.fdl` (excerpt) +### `addressbook.fdl`(节选) ```protobuf package addressbook; @@ -79,7 +77,7 @@ message AddressBook [id=103] { } ``` -### `auto_id.fdl` (excerpt) +### `auto_id.fdl`(节选) ```protobuf package auto_id; @@ -114,17 +112,17 @@ union Wrapper { ## Java -### Output Layout +### 输出布局 -For `package addressbook`, Java output is generated under: +对于 `package addressbook`,Java 输出通常位于: - `/addressbook/` -- Type files: `AddressBook.java`, `Person.java`, `Dog.java`, `Cat.java`, `Animal.java` -- Registration helper: `AddressbookForyRegistration.java` +- 类型文件:`AddressBook.java`、`Person.java`、`Dog.java`、`Cat.java`、`Animal.java` +- 注册辅助类:`AddressbookForyRegistration.java` -### Type Generation +### 类型生成 -Messages generate Java classes with `@ForyField`, default constructors, getters/setters, and byte helpers: +message 会生成带 `@ForyField`、默认构造器、getter/setter 以及字节辅助方法的 Java 类: ```java public class Person { @@ -156,7 +154,7 @@ public class Person { } ``` -Unions generate classes extending `org.apache.fory.type.union.Union`: +union 会生成继承 `org.apache.fory.type.union.Union` 的类: ```java public final class Animal extends Union { @@ -177,9 +175,9 @@ public final class Animal extends Union { } ``` -### Registration +### 注册 -Generated registration helper: +生成的注册辅助方法: ```java public static void register(Fory fory) { @@ -194,7 +192,7 @@ public static void register(Fory fory) { } ``` -For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs (for example from `auto_id.fdl`): +对于未显式 `[id=...]` 的 schema,注册代码会使用计算得到的数值 ID(例如 `auto_id.fdl`): ```java resolver.register(Status.class, 1124725126L); @@ -204,7 +202,7 @@ resolver.registerUnion(Envelope.Detail.class, 1609214087L, new org.apache.fory.s resolver.register(Envelope.Payload.class, 2862577837L); ``` -If `option enable_auto_type_id = false;` is set, registration uses namespace and type name: +若设置 `option enable_auto_type_id = false;`,则按命名空间与类型名注册: ```java resolver.register(Config.class, "myapp.models", "Config"); @@ -215,7 +213,7 @@ resolver.registerUnion( new org.apache.fory.serializer.UnionSerializer(fory, Holder.class)); ``` -### Usage +### 使用示例 ```java Person person = new Person(); @@ -228,15 +226,15 @@ Person restored = Person.fromBytes(data); ## Python -### Output Layout +### 输出布局 -Python output is one module per schema file, for example: +Python 每个 schema 文件生成一个模块,例如: - `/addressbook.py` -### Type Generation +### 类型生成 -Unions generate a case enum plus a `Union` subclass with typed helpers: +union 生成 case 枚举与 `Union` 子类,并提供类型化辅助方法: ```python class AnimalCase(Enum): @@ -255,7 +253,7 @@ class Animal(Union): def set_dog(self, v: Dog) -> None: ... ``` -Messages generate `@pyfory.dataclass` types, and nested types stay nested: +message 生成 `@pyfory.dataclass` 类型,嵌套类型保持嵌套: ```python @pyfory.dataclass @@ -279,9 +277,9 @@ class Person: def from_bytes(cls, data: bytes) -> "Person": ... ``` -### Registration +### 注册 -Generated registration function: +生成注册函数: ```python def register_addressbook_types(fory: pyfory.Fory): @@ -294,7 +292,7 @@ def register_addressbook_types(fory: pyfory.Fory): fory.register_type(AddressBook, type_id=103) ``` -For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs: +未显式 `[id=...]` 时,注册代码使用计算得到的数值 ID: ```python fory.register_type(Status, type_id=1124725126) @@ -304,7 +302,7 @@ fory.register_union(Envelope.Detail, type_id=1609214087, serializer=Envelope.Det fory.register_type(Envelope.Payload, type_id=2862577837) ``` -If `option enable_auto_type_id = false;` is set: +若设置 `option enable_auto_type_id = false;`: ```python fory.register_type(Config, namespace="myapp.models", typename="Config") @@ -316,7 +314,7 @@ fory.register_union( ) ``` -### Usage +### 使用示例 ```python person = Person(name="Alice", pet=Animal.dog(Dog(name="Rex", bark_volume=10))) @@ -327,15 +325,15 @@ restored = Person.from_bytes(data) ## Rust -### Output Layout +### 输出布局 -Rust output is one module file per schema, for example: +Rust 每个 schema 生成一个模块文件,例如: - `/addressbook.rs` -### Type Generation +### 类型生成 -Unions map to Rust enums with `#[fory(id = ...)]` case attributes: +union 映射为 Rust enum,并用 `#[fory(id = ...)]` 声明 case ID: ```rust #[derive(ForyObject, Debug, Clone, PartialEq)] @@ -347,7 +345,7 @@ pub enum Animal { } ``` -Nested types generate nested modules: +嵌套类型生成嵌套 module: ```rust pub mod person { @@ -370,7 +368,7 @@ pub mod person { } ``` -Messages derive `ForyObject` and include `to_bytes`/`from_bytes` helpers: +message 会 `derive(ForyObject)` 并生成 `to_bytes`/`from_bytes`: ```rust #[derive(ForyObject, Debug, Clone, PartialEq, Default)] @@ -384,9 +382,9 @@ pub struct Person { } ``` -### Registration +### 注册 -Generated registration function: +生成注册函数: ```rust pub fn register_types(fory: &mut Fory) -> Result<(), fory::Error> { @@ -401,7 +399,7 @@ pub fn register_types(fory: &mut Fory) -> Result<(), fory::Error> { } ``` -For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs: +未显式 `[id=...]` 时,注册代码使用计算得到的数值 ID: ```rust fory.register::(1124725126)?; @@ -411,14 +409,14 @@ fory.register_union::(1609214087)?; fory.register::(2862577837)?; ``` -If `option enable_auto_type_id = false;` is set: +若设置 `option enable_auto_type_id = false;`: ```rust fory.register_by_namespace::("myapp.models", "Config")?; fory.register_union_by_namespace::("myapp.models", "Holder")?; ``` -### Usage +### 使用示例 ```rust let person = Person { @@ -433,15 +431,15 @@ let restored = Person::from_bytes(&bytes)?; ## C++ -### Output Layout +### 输出布局 -C++ output is one header per schema file, for example: +C++ 每个 schema 文件生成一个头文件,例如: - `/addressbook.h` -### Type Generation +### 类型生成 -Messages generate `final` classes with typed accessors and byte helpers: +message 会生成 `final` 类,并包含类型化访问器与字节辅助方法: ```cpp class Person final { @@ -467,7 +465,7 @@ class Person final { }; ``` -Optional message fields generate `has_xxx`, `mutable_xxx`, and `clear_xxx` APIs: +可选 message 字段会生成 `has_xxx`、`mutable_xxx`、`clear_xxx` API: ```cpp class Envelope final { @@ -487,7 +485,7 @@ class Envelope final { }; ``` -Unions generate `std::variant` wrappers: +union 会生成基于 `std::variant` 的封装: ```cpp class Animal final { @@ -517,11 +515,11 @@ class Animal final { }; ``` -Generated headers also include `FORY_UNION`, `FORY_FIELD_CONFIG`, `FORY_ENUM`, and `FORY_STRUCT` macros for serialization metadata. +生成头文件还会包含 `FORY_UNION`、`FORY_FIELD_CONFIG`、`FORY_ENUM`、`FORY_STRUCT` 等序列化元信息宏。 -### Registration +### 注册 -Generated registration function: +生成注册函数: ```cpp inline void register_types(fory::serialization::BaseFory& fory) { @@ -535,7 +533,7 @@ inline void register_types(fory::serialization::BaseFory& fory) { } ``` -For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs: +未显式 `[id=...]` 时,注册代码使用计算得到的数值 ID: ```cpp fory.register_enum(1124725126); @@ -545,14 +543,14 @@ fory.register_union(1609214087); fory.register_struct(2862577837); ``` -If `option enable_auto_type_id = false;` is set: +若设置 `option enable_auto_type_id = false;`: ```cpp fory.register_struct("myapp.models", "Config"); fory.register_union("myapp.models", "Holder"); ``` -### Usage +### 使用示例 ```cpp addressbook::Person person; @@ -565,17 +563,17 @@ auto restored = addressbook::Person::from_bytes(bytes.value()); ## Go -### Output Layout +### 输出布局 -Go output path depends on schema options and `--go_out`. +Go 输出路径受 schema 选项与 `--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). +对于 `addressbook.fdl`,若配置了 `go_package`,生成结果会遵循对应 import path/package(位于 `--go_out` 根目录下)。 -Without `go_package`, output uses the requested `--go_out` directory and package-derived file naming. +若未配置 `go_package`,则使用 `--go_out` 指定目录,并按 package 规则生成文件名与包名。 -### Type Generation +### 类型生成 -Nested types use underscore naming by default (`Person_PhoneType`, `Person_PhoneNumber`): +嵌套类型默认使用下划线命名(`Person_PhoneType`、`Person_PhoneNumber`): ```go type Person_PhoneType int32 @@ -592,7 +590,7 @@ type Person_PhoneNumber struct { } ``` -Messages generate structs with `fory` tags and byte helpers: +message 会生成带 `fory` tag 的 struct 与字节辅助方法: ```go type Person struct { @@ -606,7 +604,7 @@ func (m *Person) ToBytes() ([]byte, error) { ... } func (m *Person) FromBytes(data []byte) error { ... } ``` -Unions generate typed case structs with constructors/accessors/visitor APIs: +union 会生成 case struct,并提供构造器/访问器/visitor API: ```go type AnimalCase uint32 @@ -624,9 +622,9 @@ func (u Animal) AsDog() (*Dog, bool) { ... } func (u Animal) Visit(visitor AnimalVisitor) error { ... } ``` -### Registration +### 注册 -Generated registration function: +生成注册函数: ```go func RegisterTypes(f *fory.Fory) error { @@ -646,7 +644,7 @@ func RegisterTypes(f *fory.Fory) error { } ``` -For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs: +未显式 `[id=...]` 时,注册代码使用计算得到的数值 ID: ```go if err := f.RegisterEnum(Status(0), 1124725126); err != nil { ... } @@ -656,20 +654,20 @@ if err := f.RegisterUnion(Envelope_Detail{}, 1609214087, fory.NewUnionSerializer if err := f.RegisterStruct(Envelope_Payload{}, 2862577837); err != nil { ... } ``` -If `option enable_auto_type_id = false;` is set: +若设置 `option enable_auto_type_id = false;`: ```go if err := f.RegisterNamedStruct(Config{}, "myapp.models.Config"); err != nil { ... } if err := f.RegisterNamedUnion(Holder{}, "myapp.models.Holder", fory.NewUnionSerializer(...)); err != nil { ... } ``` -`go_nested_type_style` controls nested type naming: +`go_nested_type_style` 可控制嵌套类型命名风格: ```protobuf option go_nested_type_style = "camelcase"; ``` -### Usage +### 使用示例 ```go person := &Person{ @@ -687,30 +685,30 @@ if err := restored.FromBytes(data); err != nil { } ``` -## Cross-Language Notes +## 跨语言说明 -### Type ID Behavior +### 类型 ID 行为 -- Explicit `[id=...]` values are used directly in generated registration. -- 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 registration uses namespace/type-name APIs instead of numeric IDs. +- 显式 `[id=...]` 会直接用于生成注册代码。 +- 未声明类型 ID 时,生成代码会使用计算得到的数值 ID(参见 `auto_id.*` 输出)。 +- 若设置 `option enable_auto_type_id = false;`,则生成代码改为使用 namespace/type-name 注册 API,而非数值 ID。 -### Nested Type Shape +### 嵌套类型形态 -| Language | Nested type form | -| -------- | ------------------------------ | -| Java | `Person.PhoneNumber` | -| Python | `Person.PhoneNumber` | -| Rust | `person::PhoneNumber` | -| C++ | `Person::PhoneNumber` | -| Go | `Person_PhoneNumber` (default) | +| 语言 | 嵌套类型形式 | +| ------ | ---------------------------- | +| Java | `Person.PhoneNumber` | +| Python | `Person.PhoneNumber` | +| Rust | `person::PhoneNumber` | +| C++ | `Person::PhoneNumber` | +| Go | `Person_PhoneNumber`(默认) | -### Byte Helper Naming +### 字节辅助方法命名 -| Language | Helpers | -| -------- | ------------------------- | -| Java | `toBytes` / `fromBytes` | -| Python | `to_bytes` / `from_bytes` | -| Rust | `to_bytes` / `from_bytes` | -| C++ | `to_bytes` / `from_bytes` | -| Go | `ToBytes` / `FromBytes` | +| 语言 | 辅助方法名称 | +| ------ | ------------------------- | +| Java | `toBytes` / `fromBytes` | +| Python | `to_bytes` / `from_bytes` | +| Rust | `to_bytes` / `from_bytes` | +| C++ | `to_bytes` / `from_bytes` | +| Go | `ToBytes` / `FromBytes` | diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/index.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/index.md index 58a4817492..8e26cdd387 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/index.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/index.md @@ -19,15 +19,12 @@ license: | limitations under the License. --- -> 中文导读:本文档为 Fory 编译器/协议规范文档的中文译稿。为避免改变规范语义,代码片段、类型名、协议字段名保持英文,说明性文字优先翻译为中文。 - -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, Go, Rust, and C++. +Fory IDL 是 Apache Fory 的 Schema 定义语言,可实现类型安全的跨语言序列化。 +你只需定义一次数据结构,即可为 Java、Python、Go、Rust 和 C++ 生成原生数据结构代码。 ## 示例 Schema -Fory IDL provides a simple, intuitive syntax for defining cross-language data structures: +Fory IDL 提供了简单直观的语法来定义跨语言数据结构: ```protobuf package example; @@ -73,54 +70,54 @@ union Animal [id=106] { } ``` -## Why Fory IDL? +## 为什么选择 Fory IDL? -### Schema-First Development +### Schema 优先开发 -Define your data model once in Fory IDL and generate consistent, type-safe code across all languages. This ensures: +在 Fory IDL 中一次定义数据模型,即可在所有语言中生成一致且类型安全的代码。这样可以确保: -- **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 +- **类型安全**:在编译期而不是运行期发现类型错误 +- **一致性**:各语言使用相同字段名、类型和结构 +- **文档性**:Schema 本身就是可持续演进的文档 +- **可演进性**:可在所有实现中受控地进行 Schema 变更 -### Fory-Native Features +### Fory 原生能力 -Unlike generic IDLs, Fory IDL is designed specifically for Fory serialization: +与通用 IDL 不同,Fory IDL 专门为 Fory 序列化设计: -- **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 +- **引用跟踪**:通过 `ref` 一等支持共享引用和循环引用 +- **可空字段**:通过 `optional` 显式声明可空类型 +- **类型注册**:内置支持数值 ID 与基于命名空间的注册 +- **原生代码生成**:生成带 Fory 注解/宏的语言惯用代码 -### Low Integration 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 +- Java:带 `@ForyField` 注解的普通 POJO +- Python:带类型提示的 dataclass +- Go:带 struct tag 的结构体 +- Rust:带 `#[derive(ForyObject)]` 的结构体 +- C++:带 `FORY_STRUCT` 宏的结构体 -## Quick Start +## 快速开始 -### 1. Install the Compiler +### 1. 安装编译器 ```bash pip install fory-compiler ``` -Or install from source: +或从源码安装: ```bash cd compiler pip install -e . ``` -### 2. Write Your Schema +### 2. 编写 Schema -Create `example.fdl`: +创建 `example.fdl`: ```protobuf package example; @@ -132,19 +129,19 @@ message Person { } ``` -### 3. Generate Code +### 3. 生成代码 ```bash -# Generate for all languages +# 为所有语言生成 foryc example.fdl --output ./generated -# Generate for specific languages +# 为指定语言生成 foryc example.fdl --lang java,python --output ./generated ``` -### 4. Use Generated Code +### 4. 使用生成代码 -**Java:** +**Java:** ```java Person person = new Person(); @@ -153,34 +150,34 @@ person.setAge(30); byte[] data = person.toBytes(); ``` -**Python:** +**Python:** ```python import pyfory from example import Person person = Person(name="Alice", age=30) -data = bytes(person) # or `person.to_bytes()` +data = bytes(person) # 或 `person.to_bytes()` ``` -## Documentation +## 文档导航 -| Document | Description | -| ----------------------------------------------- | ------------------------------------------------- | -| [Fory IDL Syntax](schema-idl.md) | Complete language syntax and grammar | -| [Type System](schema-idl.md#type-system) | 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 IDL Support](protobuf-idl.md) | Comparison with protobuf and migration guide | -| [FlatBuffers IDL Support](flatbuffers-idl.md) | FlatBuffers mapping rules and codegen differences | +| 文档 | 说明 | +| -------------------------------------------- | ---------------------------------- | +| [Fory IDL 语法](schema-idl.md) | 完整语言语法与文法 | +| [类型系统](schema-idl.md#type-system) | 基础类型、集合类型与类型规则 | +| [编译器指南](compiler-guide.md) | CLI 选项与构建集成 | +| [生成代码](generated-code.md) | 各目标语言的输出格式 | +| [Protocol Buffers IDL 支持](protobuf-idl.md) | 与 protobuf 的对比及迁移指南 | +| [FlatBuffers IDL 支持](flatbuffers-idl.md) | FlatBuffers 映射规则与代码生成差异 | -## Key Concepts +## 核心概念 -### Field Modifiers +### 字段修饰符 -- **`optional`**: Field can be null/None -- **`ref`**: Enable reference tracking for shared/circular references -- **`list`**: Field is a list/array (alias: `repeated`) +- **`optional`**:字段可为 null/None +- **`ref`**:为共享/循环引用启用引用跟踪 +- **`list`**:字段为列表/数组(别名:`repeated`) ```protobuf message Example { @@ -190,26 +187,26 @@ message Example { } ``` -### Cross-Language Compatibility +### 跨语言兼容 -Fory IDL types map to native types in each language: +Fory IDL 类型会映射为各语言原生类型: -| Fory IDL Type | Java | Python | Go | Rust | C++ | +| Fory IDL 类型 | Java | Python | Go | Rust | C++ | | ------------- | --------- | -------------- | -------- | -------- | ------------- | | `int32` | `int` | `pyfory.int32` | `int32` | `i32` | `int32_t` | | `string` | `String` | `str` | `string` | `String` | `std::string` | | `bool` | `boolean` | `bool` | `bool` | `bool` | `bool` | -See [Type System](schema-idl.md#type-system) for complete mappings. +完整映射请参见 [类型系统](schema-idl.md#type-system)。 -## 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 +1. **使用有意义的 package 名称**:将相关类型分组管理 +2. **为性能分配类型 ID**:数值 ID 比基于名称的注册更高效 +3. **预留 ID 范围**:为后续扩展保留空隙(例如用户 100-199,订单 200-299) +4. **显式使用 `optional`**:清晰表达可空语义 +5. **共享对象使用 `ref`**:对象可能被多处引用时开启引用跟踪 -## Examples +## 示例 -See the [examples](https://github.com/apache/fory/tree/main/compiler/examples) directory for complete working examples. +完整可运行示例见 [examples](https://github.com/apache/fory/tree/main/compiler/examples) 目录。 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/protobuf-idl.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/protobuf-idl.md index 2a6865d1e2..d5bb1d8791 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/protobuf-idl.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/protobuf-idl.md @@ -19,56 +19,50 @@ license: | limitations under the License. --- -> 中文导读:本文档为 Fory 编译器/协议规范文档的中文译稿。为避免改变规范语义,代码片段、类型名、协议字段名保持英文,说明性文字优先翻译为中文。 - 本页说明 Apache Fory 如何处理 Protocol Buffers(`.proto`)schema、protobuf 概念如何映射到 Fory,以及 protobuf 专用 Fory 扩展选项的使用方式。 ## 本页内容 -- Choosing protobuf vs Fory for your use case -- Syntax and semantic differences that matter during migration -- Supported Fory extension options in protobuf files -- Practical migration patterns from protobuf to Fory +- 如何在具体场景下选择 protobuf 或 Fory +- 迁移时需要关注的语法与语义差异 +- `.proto` 文件中支持的 Fory 扩展选项 +- 从 protobuf 迁移到 Fory 的实践路径 ## 快速决策指南 -| Situation | Recommended Format | -| ------------------------------------------------------------- | ------------------ | -| You are building gRPC APIs and rely on protobuf tooling | Protocol Buffers | -| You need maximum object-graph performance and ref tracking | Fory | -| You need circular/shared references in serialized data | Fory | -| You need strong unknown-field behavior for wire compatibility | Protocol Buffers | -| You need native structs/classes instead of protobuf wrappers | Fory | +| 场景 | 建议格式 | +| ----------------------------------------------------- | ---------------- | +| 主要构建 gRPC API,依赖 protobuf 工具链 | Protocol Buffers | +| 需要极致对象图性能与引用跟踪 | Fory | +| 需要在序列化数据中表达循环/共享引用 | Fory | +| 需要强 unknown-field 语义保证线格式兼容 | Protocol Buffers | +| 希望直接使用原生 struct/class,而非 protobuf 包装类型 | Fory | ## Protobuf 与 Fory 对比 -| 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 | In progress (active development) | +| 维度 | Protocol Buffers | Fory | +| --------- | --------------------- | ---------------------- | +| 主要目标 | RPC/消息契约 | 高性能对象序列化 | +| 编码模型 | Tag-Length-Value | Fory 二进制协议 | +| 引用跟踪 | 非内建 | 一等支持(`ref`) | +| 循环引用 | 不支持 | 支持 | +| 未知字段 | 保留 | 不保留 | +| 生成类型 | protobuf 专用模型类型 | 语言原生构造 | +| gRPC 生态 | 原生成熟 | 持续建设中(活跃开发) | -Fory gRPC support is under active development. For production gRPC -workflows today, protobuf remains the mature/default choice. +Fory 的 gRPC 支持仍在持续开发中。当前生产级 gRPC 工作流里,protobuf 仍是更成熟的默认选择。 ## 为什么使用 Apache Fory -- Idiomatic generated code: Fory IDL generates language-idiomatic classes and - structs that can be used directly as domain objects. -- Faster serialization: In Fory benchmarks, Fory can be around 10x faster than - protobuf for object serialization workloads. -- Better graph modeling: Shared and circular references are first-class features - instead of application-level ID-link workarounds. +- **代码更贴近语言习惯**:Fory IDL 生成的类和结构体可直接作为业务领域对象使用。 +- **序列化性能更高**:在 Fory 基准中,Fory 在对象序列化场景中可显著快于 protobuf。 +- **对象图表达更自然**:共享引用和循环引用是内建能力,无需通过业务层 ID 关联绕过。 -See benchmark details under [Performance References](#performance-references). +性能细节请参见 [性能参考](#性能参考)。 -## Syntax and Semantic Mapping +## 语法与语义映射 -### Package and File Options +### Package 与文件级选项 **Protocol Buffers** @@ -85,10 +79,9 @@ option go_package = "example.com/models"; package example.models; ``` -Fory uses one package namespace for cross-language registration. Language-specific -package placement is still configurable in code generation. +Fory 使用统一 package 命名空间做跨语言注册。语言特定的包路径仍可在代码生成阶段单独配置。 -### Message and Enum Definitions +### Message 与 Enum 定义 **Protocol Buffers** @@ -126,16 +119,15 @@ enum Status [id=102] { } ``` -Key differences: +关键差异: -- Fory can assign stable type IDs directly (`[id=...]`). -- Fory uses `list` (with `repeated T` as alias). -- Enum naming conventions are language-driven instead of protobuf prefix style. +- Fory 可直接分配稳定类型 ID(`[id=...]`)。 +- Fory 使用 `list`(`repeated T` 为兼容别名)。 +- 枚举命名更偏向语言习惯,而非 protobuf 前缀风格。 -### `oneof` to `union` +### `oneof` 到 `union` -Protobuf `oneof` is translated to a nested Fory `union` plus an optional field -referencing that union. +protobuf 的 `oneof` 会被翻译为嵌套 Fory `union`,并增加一个可选字段指向该 union。 **Protocol Buffers** @@ -148,7 +140,7 @@ message Event { } ``` -**Fory-style shape after translation** +**转换后的 Fory 结构** ```protobuf message Event { @@ -160,42 +152,42 @@ message Event { } ``` -Notes: +说明: -- Union case IDs are derived from the original `oneof` field numbers. -- The synthetic union field uses the smallest `oneof` case number. +- union case ID 来自原 `oneof` 字段号。 +- 自动生成的 union 引用字段使用 `oneof` 中最小字段号。 -### Imports and Well-Known Types +### Import 与 Well-Known Types -Protobuf imports are supported. Common well-known types map directly: +支持 protobuf import。常见 well-known types 会直接映射: - `google.protobuf.Timestamp` -> `timestamp` - `google.protobuf.Duration` -> `duration` - `google.protobuf.Any` -> `any` -## 类型映射 Highlights - -| Protobuf Type | Fory Mapping | -| ---------------------------------------- | ---------------------------------------- | -| `bool` | `bool` | -| `int32`, `uint32` | variable-length 32-bit integer kinds | -| `sint32` | zigzag 32-bit integer | -| `int64`, `uint64` | variable-length 64-bit integer kinds | -| `sint64` | zigzag 64-bit integer | -| `fixed32`, `fixed64` | fixed-width unsigned integer kinds | -| `sfixed32`, `sfixed64` | fixed-width signed integer kinds | -| `float`, `double` | `float32`, `float64` | -| `string`, `bytes` | `string`, `bytes` | -| `repeated T` | `list` | -| `map` | `map` | -| `optional T` | `optional T` | -| `oneof` | `union` + optional union reference field | -| `int64 [(fory).type = "tagged_int64"]` | `tagged_int64` encoding | -| `uint64 [(fory).type = "tagged_uint64"]` | `tagged_uint64` encoding | - -## Fory Extension Options (Protobuf) - -Fory-specific options in `.proto` use the `(fory).` prefix. +## 类型映射要点 + +| Protobuf Type | Fory 映射 | +| ---------------------------------------- | ----------------------------- | +| `bool` | `bool` | +| `int32`, `uint32` | 可变长 32 位整型家族 | +| `sint32` | zigzag 32 位整型 | +| `int64`, `uint64` | 可变长 64 位整型家族 | +| `sint64` | zigzag 64 位整型 | +| `fixed32`, `fixed64` | 定长无符号整型家族 | +| `sfixed32`, `sfixed64` | 定长有符号整型家族 | +| `float`, `double` | `float32`, `float64` | +| `string`, `bytes` | `string`, `bytes` | +| `repeated T` | `list` | +| `map` | `map` | +| `optional T` | `optional T` | +| `oneof` | `union` + 可选 union 引用字段 | +| `int64 [(fory).type = "tagged_int64"]` | `tagged_int64` 编码 | +| `uint64 [(fory).type = "tagged_uint64"]` | `tagged_uint64` 编码 | + +## Fory 扩展选项(Protobuf) + +`.proto` 文件中的 Fory 专用选项使用 `(fory).` 前缀。 ```protobuf option (fory).enable_auto_type_id = true; @@ -206,46 +198,46 @@ message TreeNode { } ``` -### File-Level Options +### 文件级选项 -| Option | Type | Description | -| ------------------------------------ | ------ | -------------------------------------------------------------- | -| `(fory).use_record_for_java_message` | bool | Generate Java records for all messages in this file | -| `(fory).polymorphism` | bool | Enable polymorphic serialization metadata by default | -| `(fory).enable_auto_type_id` | bool | Auto-generate type IDs when omitted (compiler default is true) | -| `(fory).evolving` | bool | Default schema-evolution behavior for messages | -| `(fory).go_nested_type_style` | string | Go nested naming style: `underscore` (default) or `camelcase` | +| 选项 | 类型 | 说明 | +| ------------------------------------ | ------ | --------------------------------------------------- | +| `(fory).use_record_for_java_message` | bool | 对该文件所有 message 生成 Java record | +| `(fory).polymorphism` | bool | 默认开启多态序列化元信息 | +| `(fory).enable_auto_type_id` | bool | 缺失时自动生成类型 ID(编译器默认 true) | +| `(fory).evolving` | bool | message 的默认 schema 演进行为 | +| `(fory).go_nested_type_style` | string | Go 嵌套命名风格:`underscore`(默认)或 `camelcase` | -### Message and Enum Options +### Message 与 Enum 级选项 -| Option | Applies To | Type | Description | -| ---------------------------- | ------------- | ------ | ---------------------------------------- | -| `(fory).id` | message, enum | int | Explicit type ID for registration | -| `(fory).alias` | message, enum | string | Alternate name used for auto-ID hashing | -| `(fory).evolving` | message | bool | Override file-level evolution setting | -| `(fory).use_record_for_java` | message | bool | Generate Java record for this message | -| `(fory).deprecated` | message, enum | bool | Mark type as deprecated | -| `(fory).namespace` | message | string | Override default package-based namespace | +| 选项 | 作用对象 | 类型 | 说明 | +| ---------------------------- | ------------- | ------ | ----------------------------- | +| `(fory).id` | message, enum | int | 显式类型 ID(用于注册) | +| `(fory).alias` | message, enum | string | 自动 ID 哈希使用的别名 | +| `(fory).evolving` | message | bool | 覆盖文件级演进设置 | +| `(fory).use_record_for_java` | message | bool | 为该 message 生成 Java record | +| `(fory).deprecated` | message, enum | bool | 标记类型为弃用 | +| `(fory).namespace` | message | string | 覆盖默认 package 命名空间 | -### Field-Level Options +### 字段级选项 -| Option | Type | Description | -| ---------------------------- | ------ | ------------------------------------------------------------ | -| `(fory).ref` | bool | Enable reference tracking for this field | -| `(fory).nullable` | bool | Treat field as nullable (`optional`) | -| `(fory).weak_ref` | bool | Generate weak pointer semantics (C++/Rust codegen) | -| `(fory).thread_safe_pointer` | bool | Rust pointer flavor for ref fields (`Arc` vs `Rc`) | -| `(fory).deprecated` | bool | Mark field as deprecated | -| `(fory).type` | string | Primitive override, currently `tagged_int64`/`tagged_uint64` | +| 选项 | 类型 | 说明 | +| ---------------------------- | ------ | ----------------------------------------------------- | +| `(fory).ref` | bool | 为该字段启用引用跟踪 | +| `(fory).nullable` | bool | 将字段视为可空(`optional`) | +| `(fory).weak_ref` | bool | 生成弱指针语义(C++/Rust 代码生成) | +| `(fory).thread_safe_pointer` | bool | ref 字段在 Rust 中的指针类型(`Arc` vs `Rc`) | +| `(fory).deprecated` | bool | 标记字段为弃用 | +| `(fory).type` | string | 基础类型覆盖,目前支持 `tagged_int64`/`tagged_uint64` | -Reference option behavior: +引用相关行为: -- `weak_ref = true` implies ref tracking. -- For `repeated` fields, `(fory).ref = true` applies to list elements. -- For `map` fields, `(fory).ref = true` applies to map values. -- `weak_ref` and `thread_safe_pointer` are codegen hints for C++/Rust. +- `weak_ref = true` 隐含开启 ref 跟踪。 +- 对 `repeated` 字段,`(fory).ref = true` 作用于列表元素。 +- 对 `map` 字段,`(fory).ref = true` 作用于 map value。 +- `weak_ref` 与 `thread_safe_pointer` 是 C++/Rust 代码生成提示。 -### Option Examples by Shape +### 典型选项组合示例 ```protobuf message Graph { @@ -256,12 +248,11 @@ message Graph { } ``` -## Reference Tracking vs Protobuf IDs +## 引用跟踪 vs Protobuf ID 关联 -Protobuf itself does not preserve shared/cyclic object graphs. With Fory -protobuf extensions, you can opt into graph semantics. +protobuf 本身不保留共享/循环对象图。借助 Fory protobuf 扩展,可以显式启用对象图语义。 -**Without Fory ref options (protobuf-style IDs):** +**不使用 Fory ref 选项(protobuf 风格 ID 关联):** ```protobuf message TreeNode { @@ -271,7 +262,7 @@ message TreeNode { } ``` -**With Fory ref options (object graph):** +**使用 Fory ref 选项(对象图语义):** ```protobuf message TreeNode { @@ -280,37 +271,34 @@ message TreeNode { } ``` -## Migration Guide: Protobuf to Fory +## 迁移指南:Protobuf 到 Fory -### Step 1: Translate Schema Syntax +### 第 1 步:转换 schema 语法 -- Keep package names stable. -- Replace `repeated T` with `list` (or keep `repeated` alias). -- Add explicit `[id=...]` where you need stable numeric registration. +- 保持 package 名称稳定。 +- 将 `repeated T` 改为 `list`(或保留 `repeated` 别名)。 +- 在需要稳定数值注册的位置添加显式 `[id=...]`。 -### Step 2: Convert `oneof` and Special Types +### 第 2 步:处理 `oneof` 与特殊类型 -- `oneof` -> `union` + optional union field. -- Map protobuf well-known types to Fory primitives (`timestamp`, `duration`, `any`). +- `oneof` -> `union` + 可选 union 字段。 +- 将 protobuf well-known types 映射到 Fory 基础类型(`timestamp`、`duration`、`any`)。 -### Step 3: Replace Protobuf Workarounds with `ref` +### 第 3 步:用 `ref` 替换 protobuf 的对象图绕过方案 -Where protobuf used manual ID links for object graphs, switch to Fory `ref` -modifiers (and optional `ref(weak=true)` where needed). +若 protobuf 里通过手工 ID 关联表达对象图,迁移到 Fory 后应改用 `ref` 修饰符(必要时使用 `ref(weak=true)`)。 -### Step 4: Update Build/Codegen +### 第 4 步:更新构建与代码生成 -Replace protobuf generation steps with the Fory compiler invocation for target -languages. +将 protobuf 代码生成步骤替换为 Fory 编译器针对目标语言的生成命令。 -### Step 5: Run Compatibility Checks +### 第 5 步:执行兼容性验证 -For staged migrations, keep both formats in parallel and verify payload-level -parity with integration tests. +分阶段迁移时,可并行保留两种格式,并通过集成测试验证 payload 级一致性。 -## Coexistence Strategy +## 共存策略 -You can run protobuf and Fory in parallel during migration: +迁移期间可以并行运行 protobuf 与 Fory: ```java public byte[] serialize(Object obj, Format format) { @@ -321,16 +309,13 @@ public byte[] serialize(Object obj, Format format) { } ``` -Use translators at service boundaries while internal object-graph heavy paths -migrate first. +可在服务边界设置转换层,并优先迁移内部对象图较重的链路。 -## Performance References +## 性能参考 - Benchmarks: https://fory.apache.org/docs/introduction/benchmark - Benchmark code: https://github.com/apache/fory/tree/main/benchmarks -## Summary +## 总结 -Use protobuf when your primary concern is API contracts and gRPC ecosystem -integration. Use Fory when object-graph performance, native models, and -reference semantics are the primary concern. +当主要关注 API 契约与 gRPC 生态时,建议使用 protobuf。若主要关注对象图性能、原生数据模型与引用语义,建议使用 Fory。 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/schema-idl.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/schema-idl.md index ee420bd790..be6d5c6b2a 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/schema-idl.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/compiler/schema-idl.md @@ -19,37 +19,19 @@ license: | limitations under the License. --- -## 中文章节导读 +本文档给出 Fory IDL 的语法与语义参考,覆盖文件结构、类型系统、字段规则、选项与类型注册策略。 -本文描述 Fory IDL 的语法与语义规则,覆盖文件结构、声明、类型定义、字段约束、注解与扩展选项。它是编译器前端解析与代码生成的基础约束文档。 - -阅读时可重点关注: - -1. **文件级结构**:package、option、import 与类型声明顺序。 -2. **类型系统语法**:enum/message/union 及字段声明规则。 -3. **字段标签与属性**:字段 ID、可空、引用、默认值与兼容性约束。 -4. **命名与作用域**:类型可见性、嵌套声明与名称解析。 -5. **与 protobuf/flatbuffers 的映射关系**:迁移与互操作规则。 - -为保证编译行为一致,语法关键字、示例 schema 与标识符保持英文;说明性段落使用中文。 - -> 中文导读:本文档为 Fory 编译器/协议规范文档的中文译稿。为避免改变规范语义,代码片段、类型名、协议字段名保持英文,说明性文字优先翻译为中文。 - -本文档提供 Fory IDL 的语法与语义参考。 - -For compiler usage and build integration, see -[Compiler Guide](compiler-guide.md). For protobuf/FlatBuffers frontend mapping -rules, see [Protocol Buffers IDL Support](protobuf-idl.md) and -[FlatBuffers IDL Support](flatbuffers-idl.md). +编译器使用方式与构建集成请参见 [Compiler Guide](compiler-guide.md)。 +protobuf/FlatBuffers 前端映射请参见 [Protocol Buffers IDL Support](protobuf-idl.md) 与 [FlatBuffers IDL Support](flatbuffers-idl.md)。 ## 文件结构 -An Fory IDL file typically consists of: +一个 Fory IDL 文件通常包含: -1. Optional package declaration -2. Optional file-level options -3. Optional import statements -4. Type definitions (enums, messages, and unions) +1. 可选 `package` 声明 +2. 可选文件级 `option` +3. 可选 `import` 语句 +4. 类型定义(`enum`、`message`、`union`) ```protobuf // Optional package declaration @@ -70,7 +52,7 @@ union Event [id=103] { ... } ## 注释 -Fory IDL supports both single-line and block comments: +支持单行注释与块注释: ```protobuf // This is a single-line comment @@ -85,51 +67,51 @@ message Example { } ``` -## Package Declaration +## Package 声明 -The package declaration defines the namespace for all types in the file. +`package` 定义文件中所有类型的命名空间。 ```protobuf package com.example.models; ``` -You can optionally specify a package alias used for auto-generated type IDs: +也可以配置 alias(用于自动类型 ID 计算): ```protobuf package com.example.models alias models_v1; ``` -**Rules:** +规则: -- Optional but recommended -- Must appear before any type definitions -- Only one package declaration per file -- Used for namespace-based type registration -- Package alias is used for auto-ID hashing +- 可选但推荐 +- 必须位于任何类型定义之前 +- 每个文件最多一个 `package` +- 用于命名空间注册 +- `alias` 会参与 auto-ID 哈希 -**Language Mapping:** +语言映射: -| Language | Package Usage | -| -------- | --------------------------------- | -| Java | Java package | -| Python | Module name (dots to underscores) | -| Go | Package name (last component) | -| Rust | Module name (dots to underscores) | -| C++ | Namespace (dots to `::`) | +| 语言 | package 用法 | +| ------ | ----------------------- | +| Java | Java package | +| Python | 模块名(`.` 转 `_`) | +| Go | 包名(通常取最后一段) | +| Rust | 模块名(`.` 转 `_`) | +| C++ | 命名空间(`.` 转 `::`) | -## File-Level Options +## 文件级选项 -Options can be specified at file level to control language-specific code generation. +文件级选项用于控制语言定制代码生成。 -### Syntax +### 语法 ```protobuf option option_name = value; ``` -### Java Package Option +### Java Package 选项 -Override the Java package for generated code: +通过 `java_package` 覆盖 Java 输出包名: ```protobuf package payment; @@ -140,15 +122,15 @@ message Payment { } ``` -**Effect:** +效果: -- Generated Java files will be in `com/mycorp/payment/v1/` directory -- Java package declaration will be `package com.mycorp.payment.v1;` -- Type registration still uses the Fory IDL package (`payment`) for cross-language compatibility +- Java 文件输出到 `com/mycorp/payment/v1/` +- Java `package` 声明使用该值 +- 跨语言类型注册仍以 Fory package(如 `payment`)为准 -### Go Package Option +### Go Package 选项 -Specify the Go import path and package name: +通过 `go_package` 指定 Go import path 与包名: ```protobuf package payment; @@ -159,17 +141,11 @@ message Payment { } ``` -**Format:** `"import/path;package_name"` or just `"import/path"` (last segment used as package name) - -**Effect:** - -- Generated Go files will have `package paymentv1` -- The import path can be used in other Go code -- Type registration still uses the Fory IDL package (`payment`) for cross-language compatibility +格式:`"import/path;package_name"` 或仅 `"import/path"`(包名取最后一段)。 -### Java Outer Classname Option +### Java Outer Classname 选项 -Generate all types as inner classes of a single outer wrapper class: +将多个类型包装到一个外层类: ```protobuf package payment; @@ -186,49 +162,11 @@ message Payment { } ``` -**Effect:** - -- Generates a single file `DescriptorProtos.java` instead of separate files -- All enums and messages become `public static` inner classes -- The outer class is `public final` with a private constructor -- Useful for grouping related types together - -**Generated structure:** - -```java -public final class DescriptorProtos { - private DescriptorProtos() {} - - public static enum Status { - UNKNOWN, - ACTIVE; - } - - public static class Payment { - private String id; - private Status status; - // ... - } -} -``` - -**Combined with java_package:** +默认会生成单文件,枚举与消息作为静态内部类型。 -```protobuf -package payment; -option java_package = "com.example.proto"; -option java_outer_classname = "PaymentProtos"; +### Java Multiple Files 选项 -message Payment { - string id = 1; -} -``` - -This generates `com/example/proto/PaymentProtos.java` with all types as inner classes. - -### Java Multiple Files Option - -Control whether types are generated in separate files or as inner classes: +控制 Java 是否拆分多文件: ```protobuf package payment; @@ -244,1171 +182,556 @@ message Receipt { } ``` -**Behavior:** - -| `java_outer_classname` | `java_multiple_files` | Result | -| ---------------------- | --------------------- | ------------------------------------------- | -| Not set | Any | Separate files (one per type) | -| Set | `false` (default) | Single file with all types as inner classes | -| Set | `true` | Separate files (overrides outer class) | +行为: -**Effect of `java_multiple_files = true`:** +| `java_outer_classname` | `java_multiple_files` | 结果 | +| ---------------------- | --------------------- | ---------------- | +| 未设置 | 任意 | 每个类型一个文件 | +| 已设置 | `false`(默认) | 单文件 + 内部类 | +| 已设置 | `true` | 强制拆分为多文件 | -- Each top-level enum and message gets its own `.java` file -- Overrides `java_outer_classname` behavior -- Useful when you want separate files but still specify an outer class name for other purposes - -**Example without java_multiple_files (default):** - -```protobuf -option java_outer_classname = "PaymentProtos"; -// Generates: PaymentProtos.java containing Payment and Receipt as inner classes -``` - -**Example with java_multiple_files = true:** - -```protobuf -option java_outer_classname = "PaymentProtos"; -option java_multiple_files = true; -// Generates: Payment.java, Receipt.java (separate files) -``` - -### Multiple Options - -Multiple options can be specified: +### 多个选项组合 ```protobuf package payment; option java_package = "com.mycorp.payment.v1"; option go_package = "github.com/mycorp/apis/gen/payment/v1;paymentv1"; option deprecated = true; - -message Payment { - string id = 1; -} ``` -### Protobuf Extension Syntax +### Protobuf 扩展语法说明 -In `.fdl` files, use native Fory IDL syntax only (for example, `[id=100]`, `ref`, -`optional`, `nullable=true`). +在 `.fdl` 中请使用 Fory 原生语法(如 `[id=100]`、`ref`、`optional`、`nullable=true`)。 +`(fory).xxx` 形式仅用于 `.proto`(protobuf 前端)。 -Protobuf extension syntax with `(fory).` is for `.proto` files and the protobuf -frontend only. +### 选项优先级 -For protobuf extension options, see -[Protocol Buffers IDL Support](protobuf-idl.md#fory-extension-options-protobuf). +语言包路径优先级: -### Option Priority +1. 命令行覆盖(最高) +2. 语言选项(`java_package`、`go_package`) +3. Fory IDL `package`(兜底) -For language-specific packages: +### 跨语言类型注册 -1. Command-line package override (highest priority) -2. Language-specific option (`java_package`, `go_package`) -3. Fory IDL package declaration (fallback) - -**Example:** - -```protobuf -package myapp.models; -option java_package = "com.example.generated"; -``` +默认情况下,注册名由 `package + type name`(或类型 ID)确定。建议长期保持 `package` 稳定,以避免跨版本注册不一致。 -| Scenario | Java Package Used | -| ------------------------- | ------------------------- | -| No override | `com.example.generated` | -| CLI: `--package=override` | `override` | -| No java_package option | `myapp.models` (fallback) | +## Import 语句 -### Cross-Language Type Registration - -Language-specific options only affect where code is generated, not the type namespace used for serialization. This ensures cross-language compatibility: - -```protobuf -package myapp.models; -option java_package = "com.mycorp.generated"; -option go_package = "github.com/mycorp/gen;genmodels"; - -message User { - string name = 1; -} -``` - -All languages will register `User` with namespace `myapp.models`, enabling: - -- Java serialized data → Go deserialization -- Go serialized data → Java deserialization -- Any language combination works seamlessly - -## Import Statement - -Import statements allow you to use types defined in other Fory IDL files. - -### Basic Syntax +### 基本语法 ```protobuf -import "path/to/file.fdl"; +import "common/types.fdl"; ``` -### Multiple Imports +### 多个导入 ```protobuf import "common/types.fdl"; -import "common/enums.fdl"; -import "models/address.fdl"; +import "domain/user.fdl"; +import "domain/order.fdl"; ``` -### Path Resolution +### 路径解析 -Import paths are resolved relative to the importing file: +导入解析顺序: -``` -project/ -├── common/ -│ └── types.fdl -├── models/ -│ ├── user.fdl # import "../common/types.fdl" -│ └── order.fdl # import "../common/types.fdl" -└── main.fdl # import "common/types.fdl" -``` +1. 导入者文件所在目录 +2. 命令行 `-I/--proto_path/--import_path` 指定目录(按给定顺序) -**Rules:** - -- Import paths are quoted strings (double or single quotes) -- Paths are resolved relative to the importing file's directory -- Imported types become available as if defined in the current file -- Circular imports are detected and reported as errors -- Transitive imports work (if A imports B and B imports C, A has access to C's types) - -### Complete Example - -**common/types.fdl:** +### 完整示例 ```protobuf -package common; +// src/main.fdl +package app; -enum Status [id=100] { - PENDING = 0; - ACTIVE = 1; - COMPLETED = 2; -} +import "common.fdl"; +import "models/user.fdl"; -message Address [id=101] { - string street = 1; - string city = 2; - string country = 3; +message Main { + common.Meta meta = 1; + models.User user = 2; } ``` -**models/user.fdl:** - -```protobuf -package models; -import "../common/types.fdl"; - -message User [id=200] { - string id = 1; - string name = 2; - Address home_address = 3; // Uses imported type - Status status = 4; // Uses imported enum -} -``` - -### Unsupported Import Syntax - -The following protobuf import modifiers are **not supported**: - -```protobuf -// NOT SUPPORTED - will produce an error -import public "other.fdl"; -import weak "other.fdl"; -``` +### 不支持的 import 写法 -**`import public`**: Fory IDL uses a simpler import model. All imported types are available to the importing file only. Re-exporting is not supported. Import each file directly where needed. +- URL 形式(如 `https://...`) +- 绝对路径依赖(不推荐,会破坏可移植性) -**`import weak`**: Fory IDL requires all imports to be present at compile time. Optional dependencies are not supported. +### import 错误 -### Import Errors +典型错误: -The compiler reports errors for: +- 文件不存在 +- 搜索路径未包含依赖目录 +- 同名文件冲突导致解析到错误版本 -- **File not found**: The imported file doesn't exist -- **Circular import**: A imports B which imports A (directly or indirectly) -- **Parse errors**: Syntax errors in imported files -- **Unsupported syntax**: `import public` or `import weak` +## Enum 定义 -## Enum Definition - -Enums define a set of named integer constants. - -### Basic Syntax +### 基本语法 ```protobuf enum Status { - PENDING = 0; + UNKNOWN = 0; ACTIVE = 1; - COMPLETED = 2; + DISABLED = 2; } ``` -### With Explicit Type ID +### 显式类型 ID ```protobuf -enum Status [id=100] { - PENDING = 0; +enum Status [id=101] { + UNKNOWN = 0; ACTIVE = 1; - COMPLETED = 2; + DISABLED = 2; } ``` -### Reserved Values - -Reserve field numbers or names to prevent reuse: +### 预留值 ```protobuf enum Status { - reserved 2, 15, 9 to 11, 40 to max; // Reserved numbers - reserved "OLD_STATUS", "DEPRECATED"; // Reserved names - PENDING = 0; - ACTIVE = 1; - COMPLETED = 3; -} -``` - -### Enum Type Options - -Enum-level options are declared inline in `[]` after the enum name: - -```protobuf -enum Status [deprecated=true] { - PENDING = 0; + UNKNOWN = 0; ACTIVE = 1; + reserved 2, 3; + reserved 10 to 20; } ``` -FDL does not support `option ...;` statements inside enum bodies. - -**Unsupported:** - -- `allow_alias` is **not supported**. Each enum value must have a unique integer. - -### Language Mapping - -| Language | Implementation | -| -------- | -------------------------------------- | -| Java | `enum Status { UNKNOWN, ACTIVE, ... }` | -| Python | `class Status(IntEnum): UNKNOWN = 0` | -| Go | `type Status int32` with constants | -| Rust | `#[repr(i32)] enum Status { Unknown }` | -| C++ | `enum class Status : int32_t { ... }` | - -### Enum Prefix Stripping - -When enum values use a protobuf-style prefix (enum name in UPPER_SNAKE_CASE), the compiler automatically strips the prefix for languages with scoped enums: - -```protobuf -// Input with prefix -enum DeviceTier { - DEVICE_TIER_UNKNOWN = 0; - DEVICE_TIER_TIER1 = 1; - DEVICE_TIER_TIER2 = 2; -} -``` - -**Generated code:** +### enum 类型选项 -| Language | Output | Style | -| -------- | ----------------------------------------- | -------------- | -| Java | `UNKNOWN, TIER1, TIER2` | Scoped enum | -| Rust | `Unknown, Tier1, Tier2` | Scoped enum | -| C++ | `UNKNOWN, TIER1, TIER2` | Scoped enum | -| Python | `UNKNOWN, TIER1, TIER2` | Scoped IntEnum | -| Go | `DeviceTierUnknown, DeviceTierTier1, ...` | Unscoped const | +常见:`id`、`alias`、`deprecated`。 -**Note:** The prefix is only stripped if the remainder is a valid identifier. For example, `DEVICE_TIER_1` is kept unchanged because `1` is not a valid identifier name. +### 语言映射 -**Grammar:** +- Java:`enum` +- Python:`IntEnum` +- Go:`type + const` +- Rust:`repr(i32)` 枚举 +- C++:`enum class` -``` -enum_def := 'enum' IDENTIFIER [type_options] '{' enum_body '}' -type_options := '[' type_option (',' type_option)* ']' -type_option := IDENTIFIER '=' option_value -enum_body := (reserved_stmt | enum_value)* -reserved_stmt := 'reserved' reserved_items ';' -enum_value := IDENTIFIER '=' INTEGER ';' -``` - -**Rules:** - -- Enum names must be unique within the file -- Enum values must have explicit integer assignments -- Value integers must be unique within the enum (no aliases) -- Type ID (`[id=100]`) is optional for enums but recommended for cross-language use - -**Example with All Features:** - -```protobuf -// HTTP status code categories -enum HttpCategory [id=200] { - reserved 10 to 20; // Reserved for future use - reserved "UNKNOWN"; // Reserved name - INFORMATIONAL = 1; - SUCCESS = 2; - REDIRECTION = 3; - CLIENT_ERROR = 4; - SERVER_ERROR = 5; -} -``` +### 枚举前缀处理 -## Message Definition +针对 protobuf 风格 `TYPE_NAME_VALUE`,生成器通常会按语言习惯去除冗余前缀,使 API 更自然。 -Messages define structured data types with typed fields. +## Message 定义 -### Basic Syntax +### 基本语法 ```protobuf -message Person { - string name = 1; - int32 age = 2; -} -``` - -### With Explicit Type ID - -```protobuf -message Person [id=101] { +message User { string name = 1; int32 age = 2; } ``` -### Without Explicit Type ID +### 显式类型 ID ```protobuf -message Person { // Auto-generated when enable_auto_type_id = true +message User [id=100] { string name = 1; int32 age = 2; } ``` -### Language Mapping +### 无显式类型 ID -| Language | Implementation | -| -------- | ----------------------------------- | -| Java | POJO class with getters/setters | -| Python | `@dataclass` class | -| Go | Struct with exported fields | -| Rust | Struct with `#[derive(ForyObject)]` | -| C++ | Struct with `FORY_STRUCT` macro | +未声明 `[id=...]` 时,编译器可按配置自动生成类型 ID,或使用 namespace/name 注册。 -Type IDs control cross-language registration for messages, unions, and enums. See -[Type IDs](#type-ids) for auto-generation, aliases, and collision handling. +### 语言映射 -### Reserved Fields +- Java:类 / record(按选项) +- Python:dataclass +- Go:struct +- Rust:struct +- C++:class/struct + 宏元信息 -Reserve field numbers or names to prevent reuse after removing fields: +### 预留字段 ```protobuf message User { - reserved 2, 15, 9 to 11; // Reserved field numbers - reserved "old_field", "temp"; // Reserved field names - string id = 1; - string name = 3; -} -``` - -### Message Type Options - -Message-level options are declared inline in `[]` after the message name: - -```protobuf -message User [deprecated=true] { - string id = 1; - string name = 2; + string name = 1; + reserved 2, 3; + reserved 10 to 20; } ``` -FDL does not support `option ...;` statements inside message or enum bodies. - -**Grammar:** - -``` -message_def := 'message' IDENTIFIER [type_options] '{' message_body '}' -type_options := '[' type_option (',' type_option)* ']' -type_option := IDENTIFIER '=' option_value -message_body := (reserved_stmt | nested_type | field_def)* -nested_type := enum_def | message_def | union_def -``` - -**Rules:** - -- Type IDs follow the rules in [Type IDs](#type-ids). +### message 类型选项 -## Nested Types +常见选项:`id`、`alias`、`evolving`、`deprecated`、`namespace`、`use_record_for_java`。 -Messages can contain nested message, enum, and union definitions. This is useful for defining types that are closely related to their parent message. +## 嵌套类型 -### Nested Messages +### 嵌套 message ```protobuf -message SearchResponse { - message Result { - string url = 1; - string title = 2; - list snippets = 3; - } - list results = 1; -} -``` - -### Nested Enums - -```protobuf -message Container { - enum Status { - STATUS_UNKNOWN = 0; - STATUS_ACTIVE = 1; - STATUS_INACTIVE = 2; +message Person { + message PhoneNumber { + string number = 1; } - Status status = 1; + PhoneNumber phone = 1; } ``` -### Qualified Type Names - -Nested types can be referenced from other messages using qualified names (Parent.Child): +### 嵌套 enum ```protobuf -message SearchResponse { - message Result { - string url = 1; - string title = 2; +message Person { + enum PhoneType { + MOBILE = 0; + HOME = 1; } -} - -message SearchResultCache { - // Reference nested type with qualified name - SearchResponse.Result cached_result = 1; - list all_results = 2; + PhoneType type = 1; } ``` -### Deeply Nested Types +### 限定类型名 -Nesting can be multiple levels deep: +可使用完整限定名引用嵌套类型,例如 `Person.PhoneNumber`。 -```protobuf -message Outer { - message Middle { - message Inner { - string value = 1; - } - Inner inner = 1; - } - Middle middle = 1; -} - -message OtherMessage { - // Reference deeply nested type - Outer.Middle.Inner deep_ref = 1; -} -``` +### 深层嵌套类型 -### Language-Specific Generation +支持多层嵌套,但建议控制层级,避免可读性下降。 -| Language | Nested Type Generation | -| -------- | --------------------------------------------------------------------------------- | -| Java | Static inner classes (`SearchResponse.Result`) | -| Python | Nested classes within dataclass | -| Go | Flat structs with underscore (`SearchResponse_Result`, configurable to camelcase) | -| Rust | Nested modules (`search_response::Result`) | -| C++ | Nested classes (`SearchResponse::Result`) | +### 各语言生成形态 -**Note:** Go defaults to underscore-separated nested names; set `option go_nested_type_style = "camelcase";` to use concatenated names. Rust emits nested modules for nested types. +| 语言 | 嵌套类型形态 | +| ------ | --------------------- | +| Java | `Outer.Inner` | +| Python | `Outer.Inner` | +| Rust | `outer::Inner` | +| C++ | `Outer::Inner` | +| Go | `Outer_Inner`(默认) | -### Nested Type Rules +### 嵌套规则 -- Nested type names must be unique within their parent message -- Nested types can have their own type IDs -- Numeric type IDs must be globally unique (including nested types); see [Type IDs](#type-ids) - for auto-generation and collision handling -- Within a message, you can reference nested types by simple name -- From outside, use the qualified name (Parent.Child) +- 嵌套类型名在其父作用域内必须唯一 +- 可被同文件后续类型引用 +- 可通过 import + 限定名跨文件引用 -## Union Definition +## Union 定义 -Unions define a value that can hold exactly one of several case types. - -### Basic Syntax +### 基本语法 ```protobuf -union Animal [id=106] { +union Animal { Dog dog = 1; Cat cat = 2; } ``` -### Using a Union in a Message +### 在 message 中使用 union ```protobuf -message Person [id=100] { +message Person { Animal pet = 1; - optional Animal favorite_pet = 2; } ``` -### Rules - -- Case IDs must be unique within the union -- Cases cannot be `optional` or `ref` -- Union cases do not support field options -- Case types can be primitives, enums, messages, or other named types -- Union type IDs follow the rules in [Type IDs](#type-ids). - -**Grammar:** +### 规则 -``` -union_def := 'union' IDENTIFIER [type_options] '{' union_field* '}' -union_field := field_type IDENTIFIER '=' INTEGER ';' -``` +- case 字段号必须唯一 +- case 类型通常为消息类型或可序列化复合类型 +- 各语言会生成带 case 判别和访问器的 union 表达 -## Field Definition +## 字段定义 -Fields define the properties of a message. - -### Basic Syntax +### 基本语法 ```protobuf -field_type field_name = field_number; +string name = 1; ``` -### With Modifiers +### 带修饰符语法 ```protobuf -optional list tags = 1; // Nullable list -list tags = 2; // Elements may be null -ref list nodes = 3; // Collection tracked as a reference -list nodes = 4; // Elements tracked as references +optional string nickname = 2; +ref Node parent = 3; +list scores = 4; ``` -**Grammar:** - -``` -field_def := [modifiers] field_type IDENTIFIER '=' INTEGER ';' -modifiers := { 'optional' | 'ref' } -field_type := primitive_type | named_type | list_type | map_type -list_type := 'list' '<' { 'optional' | 'ref' } field_type '>' -``` - -Modifiers apply to the field/collection. Use `list<...>` to describe element -modifiers. `repeated` is accepted as an alias for `list`. - -### Field Modifiers +### 字段修饰符 #### `optional` -Marks the field as nullable: +声明字段可为空(null/None): ```protobuf message User { - string name = 1; // Required, non-null - optional string email = 2; // Nullable + optional string email = 1; } ``` -**Generated Code:** - -| Language | Non-optional | Optional | -| -------- | ------------------ | ----------------------------------------------- | -| Java | `String name` | `String email` with `@ForyField(nullable=true)` | -| Python | `name: str` | `name: Optional[str]` | -| Go | `Name string` | `Name *string` | -| Rust | `name: String` | `name: Option` | -| C++ | `std::string name` | `std::optional name` | - -**Default Values:** - -| Type | Default Value | -| ------------------ | ------------------- | -| Non-optional types | Language default | -| Optional types | `null`/`None`/`nil` | +建议在跨语言场景显式使用,以避免默认值差异。 #### `ref` -Enables reference tracking for shared/circular references: +开启引用跟踪,用于共享对象与循环结构: ```protobuf message Node { - string value = 1; - ref Node parent = 2; // Can point to shared object + string name = 1; + ref Node parent = 2; list children = 3; } ``` -**Use Cases:** - -- Shared objects (same object referenced multiple times) -- Circular references (object graphs with cycles) -- Tree structures with parent pointers - -**Generated Code:** - -| Language | Without `ref` | With `ref` | -| -------- | -------------- | ----------------------------------------- | -| Java | `Node parent` | `Node parent` with `@ForyField(ref=true)` | -| Python | `parent: Node` | `parent: Node = pyfory.field(ref=True)` | -| Go | `Parent Node` | `Parent *Node` with `fory:"ref"` | -| Rust | `parent: Node` | `parent: Arc` | -| C++ | `Node parent` | `std::shared_ptr parent` | - -Rust uses `Arc` by default; use `ref(thread_safe=false)` or `ref(weak=true)` -to customize pointer types. For protobuf option syntax, see -[Protocol Buffers IDL Support](protobuf-idl.md#field-level-options). +当运行时全局 ref tracking 开启时,字段级 `ref` 才会生效。 #### `list` -Marks the field as a list/array: +列表字段(`repeated` 为等价别名): ```protobuf -message Document { +message Group { list tags = 1; - list authors = 2; } ``` -**Generated Code:** - -| Language | Type | -| -------- | -------------------------- | -| Java | `List` | -| Python | `List[str]` | -| Go | `[]string` | -| Rust | `Vec` | -| C++ | `std::vector` | +### 组合修饰符 -### Combining Modifiers - -Modifiers can be combined: - -```fdl -message Example { - optional list tags = 1; // Nullable list - list aliases = 2; // Elements may be null - ref list nodes = 3; // Collection tracked as a reference - list children = 4; // Elements tracked as references - optional ref User owner = 5; // Nullable tracked reference -} -``` - -Modifiers before `list` apply to the field/collection. Modifiers after `list` -apply to elements. `repeated` is accepted as an alias for `list`. - -**List modifier mapping:** - -| Fory IDL | Java | Python | Go | Rust | C++ | -| ----------------------- | ---------------------------------------------- | --------------------------------------- | ----------------------- | --------------------- | ----------------------------------------- | -| `optional list` | `List` + `@ForyField(nullable = true)` | `Optional[List[str]]` | `[]string` + `nullable` | `Option>` | `std::optional>` | -| `list` | `List` (nullable elements) | `List[Optional[str]]` | `[]*string` | `Vec>` | `std::vector>` | -| `ref list` | `List` + `@ForyField(ref = true)` | `List[User]` + `pyfory.field(ref=True)` | `[]User` + `ref` | `Arc>` | `std::shared_ptr>` | -| `list` | `List` | `List[User]` | `[]*User` + `ref=false` | `Vec>` | `std::vector>` | - -Use `ref(thread_safe=false)` in Fory IDL (or `[(fory).thread_safe_pointer = false]` in protobuf) -to generate `Rc` instead of `Arc` in Rust. - -## Field Numbers - -Each field must have a unique positive integer identifier: +可组合使用: ```protobuf -message Example { - string first = 1; - string second = 2; - string third = 3; +message Graph { + optional ref Node root = 1; + list nodes = 2; } ``` -**Rules and best practices:** +## 字段号 -- Numbers must be unique within a message. -- Numbers must be positive integers. -- Gaps are allowed and are useful when fields are removed. -- Prefer sequential numbering from `1`. -- Never reuse a removed field number for a different field. +字段号规则: -## Type System +- 同一 message 内必须唯一 +- 必须为正整数 +- 不应复用已删除字段号(建议使用 `reserved`) +- 建议预留编号区间以便演进 -Fory IDL provides a cross-language type system for primitives, named types, and -collections. Field modifiers (`optional`, `list`, `ref`) control nullability, -collection behavior, and reference tracking (see -[Field Modifiers](#field-modifiers)). +## Type System {#type-system} + +Fory IDL 类型系统包括基础类型、命名类型和集合类型。 ### Primitive Types -| Type | Description | Size | -| --------------- | ----------------------------------------- | -------- | -| `bool` | Boolean value | 1 byte | -| `int8` | Signed 8-bit integer | 1 byte | -| `int16` | Signed 16-bit integer | 2 bytes | -| `int32` | Signed 32-bit integer (varint encoding) | 4 bytes | -| `int64` | Signed 64-bit integer (varint encoding) | 8 bytes | -| `uint8` | Unsigned 8-bit integer | 1 byte | -| `uint16` | Unsigned 16-bit integer | 2 bytes | -| `uint32` | Unsigned 32-bit integer (varint encoding) | 4 bytes | -| `uint64` | Unsigned 64-bit integer (varint encoding) | 8 bytes | -| `fixed_int32` | Signed 32-bit integer (fixed encoding) | 4 bytes | -| `fixed_int64` | Signed 64-bit integer (fixed encoding) | 8 bytes | -| `fixed_uint32` | Unsigned 32-bit integer (fixed encoding) | 4 bytes | -| `fixed_uint64` | Unsigned 64-bit integer (fixed encoding) | 8 bytes | -| `tagged_int64` | Signed 64-bit integer (tagged encoding) | 8 bytes | -| `tagged_uint64` | Unsigned 64-bit integer (tagged encoding) | 8 bytes | -| `float32` | 32-bit floating point | 4 bytes | -| `float64` | 64-bit floating point | 8 bytes | -| `string` | UTF-8 string | Variable | -| `bytes` | Binary data | Variable | -| `date` | Calendar date | Variable | -| `timestamp` | Date and time with timezone | Variable | -| `duration` | Duration | Variable | -| `decimal` | Decimal value | Variable | -| `any` | Dynamic value (runtime type) | Variable | +| 类型族 | 示例 | +| -------- | --------------------------------- | +| 布尔 | `bool` | +| 整数 | `int8/int16/int32/int64`、`uint*` | +| 浮点 | `float32`、`float64` | +| 字符串 | `string` | +| 字节数组 | `bytes` | +| 时间 | `date`、`timestamp`、`duration` | +| 动态类型 | `any` | #### Boolean -| Language | Type | Notes | -| -------- | --------------------- | ------------------ | -| Java | `boolean` / `Boolean` | Primitive or boxed | -| Python | `bool` | | -| Go | `bool` | | -| Rust | `bool` | | -| C++ | `bool` | | +`bool` 表示布尔值。 #### Integer Types -Fory IDL provides fixed-width signed integers (varint encoding for 32/64-bit by default): - -| Fory IDL Type | Size | Range | -| ------------- | ------ | ----------------- | -| `int8` | 8-bit | -128 to 127 | -| `int16` | 16-bit | -32,768 to 32,767 | -| `int32` | 32-bit | -2^31 to 2^31 - 1 | -| `int64` | 64-bit | -2^63 to 2^63 - 1 | - -**Language Mapping (Signed):** - -| Fory IDL | Java | Python | Go | Rust | C++ | -| -------- | ------- | -------------- | ------- | ----- | --------- | -| `int8` | `byte` | `pyfory.int8` | `int8` | `i8` | `int8_t` | -| `int16` | `short` | `pyfory.int16` | `int16` | `i16` | `int16_t` | -| `int32` | `int` | `pyfory.int32` | `int32` | `i32` | `int32_t` | -| `int64` | `long` | `pyfory.int64` | `int64` | `i64` | `int64_t` | - -Fory IDL provides fixed-width unsigned integers (varint encoding for 32/64-bit by default): - -| Fory IDL | Size | Range | -| -------- | ------ | ------------- | -| `uint8` | 8-bit | 0 to 255 | -| `uint16` | 16-bit | 0 to 65,535 | -| `uint32` | 32-bit | 0 to 2^32 - 1 | -| `uint64` | 64-bit | 0 to 2^64 - 1 | - -**Language Mapping (Unsigned):** - -| Fory IDL | Java | Python | Go | Rust | C++ | -| -------- | ------- | --------------- | -------- | ----- | ---------- | -| `uint8` | `short` | `pyfory.uint8` | `uint8` | `u8` | `uint8_t` | -| `uint16` | `int` | `pyfory.uint16` | `uint16` | `u16` | `uint16_t` | -| `uint32` | `long` | `pyfory.uint32` | `uint32` | `u32` | `uint32_t` | -| `uint64` | `long` | `pyfory.uint64` | `uint64` | `u64` | `uint64_t` | +支持有符号/无符号与不同位宽。跨语言场景建议明确编码策略并保持字段语义稳定。 #### Integer Encoding Variants -For 32/64-bit integers, Fory IDL uses varint encoding by default. Use explicit types when -you need fixed-width or tagged encoding: +常见编码: -| Fory IDL Type | Encoding | Notes | -| --------------- | -------- | ------------------------ | -| `fixed_int32` | fixed | Signed 32-bit | -| `fixed_int64` | fixed | Signed 64-bit | -| `fixed_uint32` | fixed | Unsigned 32-bit | -| `fixed_uint64` | fixed | Unsigned 64-bit | -| `tagged_int64` | tagged | Signed 64-bit (hybrid) | -| `tagged_uint64` | tagged | Unsigned 64-bit (hybrid) | +- `varint`:小值更省空间 +- `fixed`:固定长度,性能稳定 +- `tagged`:混合编码(特定类型可用) #### Floating-Point Types -| Fory IDL Type | Size | Precision | -| ------------- | ------ | ------------- | -| `float32` | 32-bit | ~7 digits | -| `float64` | 64-bit | ~15-16 digits | - -**Language Mapping:** - -| Fory IDL | Java | Python | Go | Rust | C++ | -| --------- | -------- | ---------------- | --------- | ----- | -------- | -| `float32` | `float` | `pyfory.float32` | `float32` | `f32` | `float` | -| `float64` | `double` | `pyfory.float64` | `float64` | `f64` | `double` | +- `float32` +- `float64` #### String Type -| Language | Type | Notes | -| -------- | ------------- | --------------------- | -| Java | `String` | Immutable | -| Python | `str` | | -| Go | `string` | Immutable | -| Rust | `String` | Owned, heap-allocated | -| C++ | `std::string` | | +`string` 使用 UTF-8 文本语义。 #### Bytes Type -| Language | Type | Notes | -| -------- | ---------------------- | --------- | -| Java | `byte[]` | | -| Python | `bytes` | Immutable | -| Go | `[]byte` | | -| Rust | `Vec` | | -| C++ | `std::vector` | | +`bytes` 用于原始二进制载荷。 #### Temporal Types ##### Date -| Language | Type | Notes | -| -------- | --------------------------- | ----------------------- | -| Java | `java.time.LocalDate` | | -| Python | `datetime.date` | | -| Go | `time.Time` | Time portion ignored | -| Rust | `chrono::NaiveDate` | Requires `chrono` crate | -| C++ | `fory::serialization::Date` | | +`date` 表示日期(不含时区时间部分)。 ##### Timestamp -| Language | Type | Notes | -| -------- | -------------------------------- | ----------------------- | -| Java | `java.time.Instant` | UTC-based | -| Python | `datetime.datetime` | | -| Go | `time.Time` | | -| Rust | `chrono::NaiveDateTime` | Requires `chrono` crate | -| C++ | `fory::serialization::Timestamp` | | +`timestamp` 表示时间点(跨语言应统一时间语义与精度预期)。 #### Any -| Language | Type | Notes | -| -------- | -------------- | -------------------- | -| Java | `Object` | Runtime type written | -| Python | `Any` | Runtime type written | -| Go | `any` | Runtime type written | -| Rust | `Box` | Runtime type written | -| C++ | `std::any` | Runtime type written | - -**Example:** - -```protobuf -enum EventType [id=120] { - CREATED = 0; - DELETED = 1; -} - -message UserCreated [id=121] { - string user_id = 1; -} - -message Envelope [id=122] { - EventType type = 1; - any payload = 2; -} -``` - -**Generated Code (`Envelope.payload`):** - -| Language | Generated Field Type | -| -------- | ----------------------- | -| Java | `Object payload` | -| Python | `payload: Any` | -| Go | `Payload any` | -| Rust | `payload: Box` | -| C++ | `std::any payload` | - -**Notes:** - -- `any` always writes a null flag (same as `nullable`) because values may be empty. -- Allowed runtime values are limited to `bool`, `string`, `enum`, `message`, and `union`. - Other primitives (numeric, bytes, date/time) and list/map are not supported; wrap them in a - message or use explicit fields instead. -- `ref` is not allowed on `any` fields (including list/map values). Wrap `any` in a message - if you need reference tracking. -- The runtime type must be registered in the target language schema/IDL registration; unknown - types fail to deserialize. +`any` 允许存储动态类型值。使用 `any` 时建议配合清晰的业务约束,避免滥用导致模型不稳定。 ### Named Types -Reference other messages, enums, or unions by name: +命名类型包括: -```protobuf -enum Status { ... } -message User { ... } +- `enum` +- `message` +- `union` -message Order { - User customer = 1; // Reference to User message - Status status = 2; // Reference to Status enum -} -``` +支持跨文件 import 和限定名引用。 ### Collection Types #### List (`list`) -Use the `list<...>` type for list fields. `repeated` is accepted as an alias. See [Field Modifiers](#field-modifiers) for -modifier combinations and language mapping. +```protobuf +list +``` -Nested collection types are not supported. Use a message wrapper if you need -`list>`, `list>`, or `map<..., list<...>>`. +等价别名:`repeated T`。 #### Map -Maps with typed keys and values: - ```protobuf -message Config { - map properties = 1; - map counts = 2; - map users = 3; -} +map ``` -**Language Mapping:** - -| Fory IDL | Java | Python | Go | Rust | C++ | -| -------------------- | ---------------------- | ----------------- | ------------------ | ----------------------- | -------------------------------- | -| `map` | `Map` | `Dict[str, int]` | `map[string]int32` | `HashMap` | `std::map` | -| `map` | `Map` | `Dict[str, User]` | `map[string]User` | `HashMap` | `std::map` | - -**Key Type Restrictions:** +约束: -- `string` (most common) -- Integer types (`int8`, `int16`, `int32`, `int64`) -- `bool` - -Avoid using messages or complex types as keys. +- `K` 一般应为可稳定比较的标量类型 +- `V` 可为任意支持类型 ### Type Compatibility Matrix -This matrix shows which type conversions are safe across languages: - -| From -> To | bool | int8 | int16 | int32 | int64 | float32 | float64 | string | -| ---------- | ---- | ---- | ----- | ----- | ----- | ------- | ------- | ------ | -| bool | Y | Y | Y | Y | Y | - | - | - | -| int8 | - | Y | Y | Y | Y | Y | Y | - | -| int16 | - | - | Y | Y | Y | Y | Y | - | -| int32 | - | - | - | Y | Y | - | Y | - | -| int64 | - | - | - | - | Y | - | - | - | -| float32 | - | - | - | - | - | Y | Y | - | -| float64 | - | - | - | - | - | - | Y | - | -| string | - | - | - | - | - | - | - | Y | +跨语言建议: -Y = Safe conversion, - = Not recommended +- 使用各语言都稳定支持的公共子集 +- 尽量避免平台相关宽度/语义差异 +- 对整数编码与可空语义显式声明 ### Best Practices -- Use `int32` as the default for most integers; use `int64` for large values. -- Use `string` for text data (UTF-8) and `bytes` for binary data. -- Use `optional` only when the field may legitimately be absent. -- Use `ref` only when needed for shared or circular references. -- Prefer `list` for ordered sequences and `map` for key-value lookups. +1. 优先使用显式字段号与稳定命名 +2. 需要可空就显式 `optional` +3. 存在共享/循环关系时使用 `ref` +4. 降低 `any` 使用范围,优先强类型建模 +5. 预留字段号与枚举值区间 ## Type IDs -Type IDs enable efficient cross-language serialization and are used for -messages, unions, and enums. When `enable_auto_type_id = true` (default) and -`id` is omitted, the compiler auto-generates one using -`MurmurHash3(utf8(package.type_name))` (32-bit) and annotates it in generated -code. When `enable_auto_type_id = false`, types without explicit IDs are -registered by namespace and name instead. Collisions are detected at -compile-time across the current file and all imports; when a collision occurs, -the compiler raises an error and asks for an explicit `id` or an `alias`. - -```protobuf -enum Color [id=100] { ... } -message User [id=101] { ... } -union Event [id=102] { ... } -``` - -Enum type IDs remain optional; if omitted they are auto-generated using the same -hash when `enable_auto_type_id = true`. +类型 ID 用于跨语言快速注册与解码匹配。 -### With Explicit Type ID +### 显式类型 ID ```protobuf -message User [id=101] { ... } -message User [id=101, deprecated=true] { ... } // Multiple options +message User [id=100] { + string name = 1; +} ``` -### Without Explicit Type ID +### 无显式类型 ID -```protobuf -message Config { ... } // Auto-generated when enable_auto_type_id = true -``` +未显式声明时可: -You can set `[alias="..."]` to change the hash source without renaming the type. +- 自动生成数值 ID(默认配置) +- 禁用自动 ID,改用 namespace/type-name 注册 -### Practical Notes +### 实践说明 -- If a type omits `id` and `enable_auto_type_id = true`, Fory generates an ID - with `MurmurHash3(utf8(package.type_name))` (32-bit). -- Package alias and type alias change the hash input and can be used to resolve - hash collisions without renaming public types. -- Manual IDs in the small varint range (`0-127`) are compact on the wire; auto - IDs are typically larger and usually consume 4-5 bytes. +- 类型 ID 在协议层面应视为稳定标识 +- 一经发布,不建议更改 +- 建议按域规划 ID 段(如 100-199 用户域) -### ID Assignment Strategy +### ID 分配策略 -```protobuf -// Enums: 100-199 -enum Status [id=100] { ... } -enum Priority [id=101] { ... } +- 核心高频模型优先分配固定 ID +- 团队统一管理 ID 区间与分配规范 +- 在 CI 中增加 ID 冲突检查 -// User domain: 200-299 -message User [id=200] { ... } -message UserProfile [id=201] { ... } +## 完整示例 -// Order domain: 300-399 -message Order [id=300] { ... } -message OrderItem [id=301] { ... } -``` +```protobuf +package demo.order; -## Complete Example +option java_package = "com.example.demo.order"; +option go_package = "github.com/example/demo/gen/order;order"; -```protobuf -// E-commerce domain model -package com.shop.models; - -// Enums with type IDs -enum OrderStatus [id=100] { - PENDING = 0; - CONFIRMED = 1; - SHIPPED = 2; - DELIVERED = 3; - CANCELLED = 4; -} +import "demo/common.fdl"; -enum PaymentMethod [id=101] { - CREDIT_CARD = 0; - DEBIT_CARD = 1; - PAYPAL = 2; - BANK_TRANSFER = 3; +enum Status [id=200] { + UNKNOWN = 0; + CREATED = 1; + PAID = 2; + SHIPPED = 3; } -// Messages with type IDs -message Address [id=200] { - string street = 1; - string city = 2; - string state = 3; - string country = 4; - string postal_code = 5; +message Item [id=201] { + string sku = 1; + int32 quantity = 2; } -message Customer [id=201] { +message User [id=202] { string id = 1; string name = 2; optional string email = 3; - optional string phone = 4; - optional Address billing_address = 5; - optional Address shipping_address = 6; } -message Product [id=202] { - string sku = 1; - string name = 2; - string description = 3; - float64 price = 4; - int32 stock = 5; - list categories = 6; - map attributes = 7; +union Animal [id=203] { + Dog dog = 1; + Cat cat = 2; } -message OrderItem [id=203] { - ref Product product = 1; // Track reference to avoid duplication - int32 quantity = 2; - float64 unit_price = 3; +message Dog [id=204] { + string name = 1; } -message Order [id=204] { - string id = 1; - ref Customer customer = 2; - list items = 3; - OrderStatus status = 4; - PaymentMethod payment_method = 5; - float64 total = 6; - optional string notes = 7; - timestamp created_at = 8; - optional timestamp shipped_at = 9; +message Cat [id=205] { + string name = 1; } -// Config without explicit type ID (auto-generated when enable_auto_type_id = true) -message ShopConfig { - string store_name = 1; - string currency = 2; - float64 tax_rate = 3; - list supported_countries = 4; +message Order [id=206] { + string id = 1; + ref User buyer = 2; + list items = 3; + Status status = 4; + map metadata = 5; + optional Animal pet = 6; } ``` -For protobuf-specific extension options and `(fory).` syntax, see -[Protocol Buffers IDL Support](protobuf-idl.md#fory-extension-options-protobuf). +## 语法摘要 -## Grammar Summary +以下为简化文法(便于快速查阅,具体以编译器实现为准): +```ebnf +file = [packageDecl] {optionDecl} {importDecl} {typeDecl} ; + +packageDecl = "package" qualifiedName ["alias" identifier] ";" ; +optionDecl = "option" identifier "=" optionValue ";" ; +importDecl = "import" stringLiteral ";" ; + +typeDecl = enumDecl | messageDecl | unionDecl ; + +enumDecl = "enum" identifier [typeOptions] "{" {enumField | reservedDecl} "}" ; +enumField = identifier "=" intLiteral ";" ; + +messageDecl = "message" identifier [typeOptions] "{" {fieldDecl | nestedTypeDecl | reservedDecl} "}" ; +unionDecl = "union" identifier [typeOptions] "{" {unionCaseDecl} "}" ; + +fieldDecl = [fieldModifier] typeRef identifier "=" intLiteral [fieldOptions] ";" ; +unionCaseDecl = typeRef identifier "=" intLiteral [fieldOptions] ";" ; + +fieldModifier = "optional" | "ref" | "list" ; + +typeRef = primitiveType | qualifiedName | listType | mapType ; +listType = "list" "<" typeRef ">" ; +mapType = "map" "<" typeRef "," typeRef ">" ; + +typeOptions = "[" optionPair {"," optionPair} "]" ; +fieldOptions = "[" optionPair {"," optionPair} "]" ; +optionPair = identifier "=" optionValue ; + +reservedDecl = "reserved" reservedItem {"," reservedItem} ";" ; +reservedItem = intLiteral | intLiteral "to" intLiteral | stringLiteral ; ``` -file := [package_decl] file_option* import_decl* type_def* - -package_decl := 'package' package_name ['alias' package_name] ';' -package_name := IDENTIFIER ('.' IDENTIFIER)* - -file_option := 'option' option_name '=' option_value ';' -option_name := IDENTIFIER - -import_decl := 'import' STRING ';' - -type_def := enum_def | message_def | union_def - -enum_def := 'enum' IDENTIFIER [type_options] '{' enum_body '}' -enum_body := (reserved_stmt | enum_value)* -enum_value := IDENTIFIER '=' INTEGER ';' - -message_def := 'message' IDENTIFIER [type_options] '{' message_body '}' -message_body := (reserved_stmt | nested_type | field_def)* -nested_type := enum_def | message_def | union_def -field_def := [modifiers] field_type IDENTIFIER '=' INTEGER [field_options] ';' - -union_def := 'union' IDENTIFIER [type_options] '{' union_field* '}' -union_field := ['repeated'] field_type IDENTIFIER '=' INTEGER [field_options] ';' -option_value := 'true' | 'false' | IDENTIFIER | INTEGER | STRING - -reserved_stmt := 'reserved' reserved_items ';' -reserved_items := reserved_item (',' reserved_item)* -reserved_item := INTEGER | INTEGER 'to' INTEGER | INTEGER 'to' 'max' | STRING - -modifiers := { 'optional' | 'ref' | 'repeated' } - -field_type := primitive_type | named_type | list_type | map_type -primitive_type := 'bool' - | 'int8' | 'int16' | 'int32' | 'int64' - | 'uint8' | 'uint16' | 'uint32' | 'uint64' - | 'fixed_int32' | 'fixed_int64' | 'fixed_uint32' | 'fixed_uint64' - | 'tagged_int64' | 'tagged_uint64' - | 'float32' | 'float64' - | 'string' | 'bytes' - | 'date' | 'timestamp' | 'duration' | 'decimal' - | 'any' -named_type := qualified_name -qualified_name := IDENTIFIER ('.' IDENTIFIER)* // e.g., Parent.Child -list_type := 'list' '<' { 'optional' | 'ref' } field_type '>' -map_type := 'map' '<' field_type ',' field_type '>' - -type_options := '[' type_option (',' type_option)* ']' -type_option := IDENTIFIER '=' option_value // e.g., id=100, deprecated=true -field_options := '[' field_option (',' field_option)* ']' -field_option := IDENTIFIER '=' option_value // e.g., deprecated=true, ref=true - -STRING := '"' [^"\n]* '"' | "'" [^'\n]* "'" -IDENTIFIER := [a-zA-Z_][a-zA-Z0-9_]* -INTEGER := '-'? [0-9]+ -``` + +实现建议:如需严谨验证,请以编译器语法解析器和测试用例为准。 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/cpp/field-configuration.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/cpp/field-configuration.md index 0c18e125ce..4dd404c290 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/cpp/field-configuration.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/cpp/field-configuration.md @@ -19,25 +19,22 @@ license: | limitations under the License. --- -> 中文导读:本页介绍字段级序列化配置,包括字段 ID、可空控制、引用跟踪、忽略字段与动态类型控制等。 -> 建议在跨语言和兼容模式场景中优先显式配置字段 ID,并在需要时开启 ref/nullable 以保证行为一致。 - -本页说明如何配置序列化的字段级元信息。 +本页说明如何在 C++ 中配置序列化字段级元信息。 ## 概述 -Apache Fory™ provides two ways to specify field-level metadata at compile time: +Apache Fory™ 在编译期提供两种字段元信息配置方式: -1. **`fory::field<>` template** - Inline metadata in struct definition -2. **`FORY_FIELD_TAGS` macro** - Non-invasive metadata added separately +1. **`fory::field<>` 模板**:在 struct 定义中内联声明元信息 +2. **`FORY_FIELD_TAGS` 宏**:在 struct 外部附加元信息(非侵入) -These enable: +这些机制可用于: -- **Tag IDs**: Assign compact numeric IDs for schema evolution -- **Nullability**: Mark pointer fields as nullable -- **Reference Tracking**: Enable reference tracking for shared pointers +- **Tag ID**:为 schema 演进分配紧凑数值 ID +- **可空控制**:将指针字段标记为可空 +- **引用跟踪**:为共享指针启用引用跟踪 -## fory::field 模板 +## `fory::field` 模板 ```cpp template @@ -46,11 +43,11 @@ class field; ### 模板参数 -| Parameter | Description | -| --------- | ------------------------------------------------ | -| `T` | The underlying field type | -| `Id` | Field tag ID (int16_t) for compact serialization | -| `Options` | Optional tags: `fory::nullable`, `fory::ref` | +| 参数 | 说明 | +| --------- | ------------------------------------------ | +| `T` | 底层字段类型 | +| `Id` | 字段 tag ID(`int16_t`),用于紧凑序列化 | +| `Options` | 可选标签:`fory::nullable`、`fory::ref` 等 | ### 基本用法 @@ -67,7 +64,7 @@ struct Person { FORY_STRUCT(Person, name, age, nickname); ``` -The `fory::field<>` wrapper is transparent - you can use it like the underlying type: +`fory::field<>` 是透明包装,可像底层类型一样使用: ```cpp Person person; @@ -79,9 +76,9 @@ int a = person.age.get(); // Explicit get() ## 标签类型 -### fory::nullable +### `fory::nullable` -Marks a smart pointer field as nullable (can be `nullptr`): +将智能指针字段标记为可空(可为 `nullptr`): ```cpp struct Node { @@ -91,9 +88,9 @@ struct Node { FORY_STRUCT(Node, name, next); ``` -**Valid for:** `std::shared_ptr`, `std::unique_ptr` +**适用类型:** `std::shared_ptr`、`std::unique_ptr` -**Note:** For nullable primitives or strings, use `std::optional` instead: +**说明:** 对原生值类型或字符串的可空语义,请使用 `std::optional`: ```cpp // Correct: use std::optional for nullable primitives @@ -103,19 +100,19 @@ fory::field, 0> optional_value; // fory::field value; // Compile error! ``` -### fory::not_null +### `fory::not_null` -Explicitly marks a pointer field as non-nullable. This is the default for smart pointers, but can be used for documentation: +显式声明指针字段不可空。虽然这是智能指针的默认行为,但可用于增强可读性: ```cpp fory::field, 0, fory::not_null> data; // Must not be nullptr ``` -**Valid for:** `std::shared_ptr`, `std::unique_ptr` +**适用类型:** `std::shared_ptr`、`std::unique_ptr` -### fory::ref +### `fory::ref` -Enables reference tracking for shared pointer fields. When multiple fields reference the same object, it will be serialized once and shared: +为共享指针字段启用引用跟踪。多个字段引用同一对象时,仅序列化一次并保持共享关系: ```cpp struct Graph { @@ -126,27 +123,27 @@ struct Graph { FORY_STRUCT(Graph, name, left, right); ``` -**Valid for:** `std::shared_ptr` only (requires shared ownership) +**适用类型:** 仅 `std::shared_ptr`(需要共享所有权) -### Combining Tags +### 组合标签 -Multiple tags can be combined for shared pointers: +共享指针可组合多个标签: ```cpp // Nullable + ref tracking fory::field, 0, fory::nullable, fory::ref> link; ``` -## Type Rules +## 类型规则 -| Type | Allowed Options | Nullability | -| -------------------- | ----------------- | ---------------------------------- | -| Primitives, strings | None | Use `std::optional` if nullable | -| `std::optional` | None | Inherently nullable | -| `std::shared_ptr` | `nullable`, `ref` | Non-null by default | -| `std::unique_ptr` | `nullable` | Non-null by default | +| 类型 | 可用选项 | 可空语义 | +| -------------------- | ----------------- | --------------------------------- | +| 原生类型、字符串 | 无 | 若需可空请使用 `std::optional` | +| `std::optional` | 无 | 天然可空 | +| `std::shared_ptr` | `nullable`、`ref` | 默认不可空 | +| `std::unique_ptr` | `nullable` | 默认不可空 | -## Complete Example +## 完整示例 ```cpp #include "fory/serialization/fory.h" @@ -191,9 +188,9 @@ int main() { } ``` -## Compile-Time Validation +## 编译期校验 -Invalid configurations are caught at compile time: +非法配置会在编译期报错: ```cpp // Error: nullable and not_null are mutually exclusive @@ -209,9 +206,9 @@ fory::field, 0, fory::ref> bad3; fory::field, 0, fory::nullable> bad4; ``` -## Backwards Compatibility +## 向后兼容 -Existing structs without `fory::field<>` wrappers continue to work: +未使用 `fory::field<>` 包装的旧 struct 仍可正常工作: ```cpp // Old style - still works @@ -229,15 +226,15 @@ struct ModernPerson { FORY_STRUCT(ModernPerson, name, age); ``` -## FORY_FIELD_TAGS Macro +## `FORY_FIELD_TAGS` 宏 -The `FORY_FIELD_TAGS` macro provides a non-invasive way to add field metadata without modifying struct definitions. This is useful for: +`FORY_FIELD_TAGS` 提供了一种非侵入式方案:无需修改 struct 定义即可附加字段元信息。适用场景: -- **Third-party types**: Add metadata to types you don't own -- **Clean structs**: Keep struct definitions as pure C++ -- **Isolated dependencies**: Confine Fory headers to serialization config files +- **第三方类型**:为非自有类型添加元信息 +- **纯净结构定义**:保持 struct 仅包含标准 C++ 类型 +- **依赖隔离**:将 Fory 头文件限制在序列化配置文件中 -### Usage +### 用法 ```cpp // user_types.h - NO fory headers needed! @@ -268,33 +265,33 @@ FORY_FIELD_TAGS(Document, ) ``` -### FORY_FIELD_TAGS Options +### `FORY_FIELD_TAGS` 选项 -| Field Type | Valid Combinations | +| 字段类型 | 合法组合 | | -------------------- | ---------------------------------------------------------------------------------------- | -| Primitives, strings | `(field, id)` only | -| `std::optional` | `(field, id)` only | -| `std::shared_ptr` | `(field, id)`, `(field, id, nullable)`, `(field, id, ref)`, `(field, id, nullable, ref)` | -| `std::unique_ptr` | `(field, id)`, `(field, id, nullable)` | +| 原生类型、字符串 | 仅 `(field, id)` | +| `std::optional` | 仅 `(field, id)` | +| `std::shared_ptr` | `(field, id)`、`(field, id, nullable)`、`(field, id, ref)`、`(field, id, nullable, ref)` | +| `std::unique_ptr` | `(field, id)`、`(field, id, nullable)` | -### API Comparison +### API 对比 -| Aspect | `fory::field<>` Wrapper | `FORY_FIELD_TAGS` Macro | -| ----------------------- | ------------------------ | ----------------------- | -| **Struct definition** | Modified (wrapped types) | Unchanged (pure C++) | -| **IDE support** | Template noise | Excellent (clean types) | -| **Third-party classes** | Not supported | Supported | -| **Header dependencies** | Required everywhere | Isolated to config | -| **Migration effort** | High (change all fields) | Low (add one macro) | +| 维度 | `fory::field<>` 包装 | `FORY_FIELD_TAGS` 宏 | +| -------------- | ------------------------ | ---------------------- | +| **结构定义** | 需要改动(包装字段类型) | 无需改动(保持纯 C++) | +| **IDE 体验** | 有模板噪音 | 更清晰(原生字段类型) | +| **第三方类型** | 不支持 | 支持 | +| **头文件依赖** | 各处都需要 | 可集中在配置文件 | +| **迁移成本** | 高(修改全部字段) | 低(新增一个宏) | -## FORY_FIELD_CONFIG Macro +## `FORY_FIELD_CONFIG` 宏 -The `FORY_FIELD_CONFIG` macro is the most powerful and flexible way to configure field-level serialization. It provides: +`FORY_FIELD_CONFIG` 是更强、更灵活的字段配置方式,提供: -- **Builder pattern API**: Fluent, chainable configuration with `F(id).option1().option2()` -- **Encoding control**: Specify how unsigned integers are encoded (varint, fixed, tagged) -- **Compile-time verification**: Field names are verified against member pointers -- **Cross-language compatibility**: Configure encoding to match other languages (Java, Rust, etc.) +- **Builder 风格 API**:链式配置 `F(id).option1().option2()` +- **编码控制**:指定无符号整数编码(varint、fixed、tagged) +- **编译期校验**:通过成员指针校验字段名 +- **跨语言兼容**:按 Java、Rust 等语言期望配置编码 ### 基本语法 @@ -308,9 +305,9 @@ FORY_FIELD_CONFIG(StructType, ); ``` -### The F() Builder +### `F()` Builder -The `fory::F(id)` factory creates a `FieldMeta` object that supports method chaining: +`fory::F(id)` 工厂函数会创建支持链式调用的 `FieldMeta` 对象: ```cpp fory::F(0) // Create with field ID 0 @@ -323,7 +320,7 @@ fory::F(0) // Create with field ID 0 .compress(false) // Disable compression ``` -**Tip:** To use `F()` without the `fory::` prefix, add a using declaration: +**提示:** 若希望省略 `fory::` 前缀,可添加 `using` 声明: ```cpp using fory::F; @@ -334,19 +331,19 @@ FORY_FIELD_CONFIG(MyStruct, ); ``` -### Encoding Options for Unsigned Integers +### 无符号整数编码选项 -For `uint32_t` and `uint64_t` fields, you can specify the wire encoding: +对于 `uint32_t` 与 `uint64_t` 字段,可显式指定线格式编码: -| Method | Type ID | Description | Use Case | -| ----------- | ------------- | ---------------------------------------------- | ------------------------------------- | -| `.varint()` | VAR_UINT32/64 | Variable-length encoding (1-5 or 1-10 bytes) | Values typically small | -| `.fixed()` | UINT32/64 | Fixed-size encoding (always 4 or 8 bytes) | Values uniformly distributed | -| `.tagged()` | TAGGED_UINT64 | Tagged hybrid encoding with size hint (uint64) | Mixed small and large values (uint64) | +| 方法 | Type ID | 说明 | 适用场景 | +| ----------- | ------------- | --------------------------------- | ------------------------ | +| `.varint()` | VAR_UINT32/64 | 变长编码(1-5 或 1-10 字节) | 数值通常较小 | +| `.fixed()` | UINT32/64 | 定长编码(固定 4 或 8 字节) | 数值分布较均匀 | +| `.tagged()` | TAGGED_UINT64 | 带大小提示的混合编码(仅 uint64) | 小值与大值混合(uint64) | -**Note:** `uint8_t` and `uint16_t` always use fixed encoding (UINT8, UINT16). +**说明:** `uint8_t` 与 `uint16_t` 始终使用定长编码(UINT8、UINT16)。 -### Complete Example +### 完整示例 ```cpp #include "fory/serialization/fory.h" @@ -411,11 +408,11 @@ int main() { } ``` -### Cross-Language Compatibility +### 跨语言兼容 -When serializing data to be read by other languages, use `FORY_FIELD_CONFIG` to match their encoding expectations: +当序列化数据会被其他语言读取时,建议通过 `FORY_FIELD_CONFIG` 显式匹配目标语言编码约定。 -**Java Compatibility:** +**Java 兼容示例:** ```cpp // Java uses these type IDs for unsigned integers: @@ -446,9 +443,9 @@ FORY_FIELD_CONFIG(JavaCompatible, ); ``` -### Schema Evolution with FORY_FIELD_CONFIG +### 使用 `FORY_FIELD_CONFIG` 做 Schema 演进 -In compatible mode, fields can have different nullability between sender and receiver: +在兼容模式下,发送端和接收端可以对字段使用不同可空策略: ```cpp // Version 1: All fields non-nullable @@ -476,32 +473,32 @@ FORY_FIELD_CONFIG(DataV2, ); ``` -### FORY_FIELD_CONFIG Options Reference - -| Method | Description | Valid For | -| ---------------- | ------------------------------------------- | -------------------------- | -| `.nullable()` | Mark field as nullable | Smart pointers, primitives | -| `.ref()` | Enable reference tracking | `std::shared_ptr` only | -| `.monomorphic()` | Mark pointer as always pointing to one type | Smart pointers | -| `.varint()` | Use variable-length encoding | `uint32_t`, `uint64_t` | -| `.fixed()` | Use fixed-size encoding | `uint32_t`, `uint64_t` | -| `.tagged()` | Use tagged hybrid encoding | `uint64_t` only | -| `.compress(v)` | Enable/disable field compression | All types | - -### Comparing Field Configuration Macros - -| Feature | `fory::field<>` | `FORY_FIELD_TAGS` | `FORY_FIELD_CONFIG` | -| ----------------------- | --------------------- | ----------------- | ------------------------- | -| **Struct modification** | Required (wrap types) | None | None | -| **Encoding control** | No | No | Yes (varint/fixed/tagged) | -| **Builder pattern** | No | No | Yes | -| **Compile-time verify** | Yes | Limited | Yes (member pointers) | -| **Cross-lang compat** | Limited | Limited | Full | -| **Recommended for** | Simple structs | Third-party types | Complex/xlang structs | - -## Related Topics - -- [Type Registration](type-registration.md) - Registering types with FORY_STRUCT -- [Schema Evolution](schema-evolution.md) - Using tag IDs for schema evolution -- [Configuration](configuration.md) - Enabling reference tracking globally -- [Cross-Language](cross-language.md) - Interoperability with Java, Rust, Python +### `FORY_FIELD_CONFIG` 选项速查 + +| 方法 | 说明 | 适用范围 | +| ---------------- | ------------------------ | ---------------------- | +| `.nullable()` | 将字段标记为可空 | 智能指针、可空值类型 | +| `.ref()` | 启用引用跟踪 | 仅 `std::shared_ptr` | +| `.monomorphic()` | 标记指针始终指向单一类型 | 智能指针 | +| `.varint()` | 变长编码 | `uint32_t`、`uint64_t` | +| `.fixed()` | 定长编码 | `uint32_t`、`uint64_t` | +| `.tagged()` | tagged 混合编码 | 仅 `uint64_t` | +| `.compress(v)` | 启用/禁用字段压缩 | 所有类型 | + +### 字段配置方案对比 + +| 特性 | `fory::field<>` | `FORY_FIELD_TAGS` | `FORY_FIELD_CONFIG` | +| ------------------- | ------------------ | ----------------- | ------------------------- | +| **需要修改 struct** | 是(包装字段类型) | 否 | 否 | +| **编码控制** | 否 | 否 | 是(varint/fixed/tagged) | +| **Builder 风格** | 否 | 否 | 是 | +| **编译期校验** | 是 | 有限 | 是(成员指针校验) | +| **跨语言兼容能力** | 有限 | 有限 | 完整 | +| **推荐场景** | 简单结构体 | 第三方类型 | 复杂/跨语言结构体 | + +## 相关主题 + +- [类型注册](type-registration.md) - 使用 FORY_STRUCT 注册类型 +- [Schema 演进](schema-evolution.md) - 基于 tag ID 的演进策略 +- [配置](configuration.md) - 全局启用引用跟踪等选项 +- [跨语言](cross-language.md) - 与 Java、Rust、Python 的互操作 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/cpp/schema-evolution.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/cpp/schema-evolution.md index 3f89d97aad..fd8c7bfcad 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/cpp/schema-evolution.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/cpp/schema-evolution.md @@ -85,7 +85,7 @@ Compatible 模式支持以下 schema 变更: | 添加新字段 | ✅ | 缺失字段使用默认值 | | 删除字段 | ✅ | 额外字段被跳过 | | 重排字段顺序 | ✅ | 按名称匹配字段,而非位置 | -| 更改可空性 | ✅ | `T` ↔ `std::optional` | +| 更改可空性 | ✅ | `T` ↔ `std::optional` | | 更改字段类型 | ❌ | 类型必须兼容 | | 重命名字段 | ❌ | 字段名必须匹配(区分大小写) | diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/go/configuration.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/go/configuration.md index ca1a0e0b24..770e5a1022 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/go/configuration.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/go/configuration.md @@ -33,12 +33,12 @@ f := fory.New() 默认设置: -| Option | Default | Description | -| ---------- | ------- | ------------------------------ | -| TrackRef | false | 关闭引用跟踪 | -| MaxDepth | 20 | 最大嵌套深度 | -| IsXlang | false | 关闭跨语言模式 | -| Compatible | false | 关闭 Schema 演进兼容模式 | +| Option | Default | Description | +| ---------- | ------- | ------------------------ | +| TrackRef | false | 关闭引用跟踪 | +| MaxDepth | 20 | 最大嵌套深度 | +| IsXlang | false | 关闭跨语言模式 | +| Compatible | false | 关闭 Schema 演进兼容模式 | ### 通过选项配置 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/go/index.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/go/index.md index 4e695875ac..a161c83606 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/go/index.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/go/index.md @@ -143,19 +143,19 @@ data, _ := f.Serialize(&User{ID: 1, Name: "Alice"}) ## 文档导航 -| 主题 | 说明 | -| -------------------------------------------- | -------------------------------------- | -| [配置](configuration.md) | 配置项与运行参数 | -| [基本序列化](basic-serialization.md) | 核心 API 与使用模式 | -| [类型注册](type-registration.md) | 序列化前的类型注册 | -| [支持类型](supported-types.md) | 完整类型支持说明 | -| [引用](references.md) | 循环引用与共享对象 | -| [Struct 标签](struct-tags.md) | 字段级配置 | -| [Schema 演进](schema-evolution.md) | 前向/后向兼容策略 | -| [跨语言](cross-language.md) | 多语言序列化 | -| [代码生成](codegen.md) | 实验性的 AOT 代码生成 | -| [线程安全](thread-safety.md) | 并发使用模式 | -| [故障排查](troubleshooting.md) | 常见问题与解决方案 | +| 主题 | 说明 | +| ------------------------------------ | --------------------- | +| [配置](configuration.md) | 配置项与运行参数 | +| [基本序列化](basic-serialization.md) | 核心 API 与使用模式 | +| [类型注册](type-registration.md) | 序列化前的类型注册 | +| [支持类型](supported-types.md) | 完整类型支持说明 | +| [引用](references.md) | 循环引用与共享对象 | +| [Struct 标签](struct-tags.md) | 字段级配置 | +| [Schema 演进](schema-evolution.md) | 前向/后向兼容策略 | +| [跨语言](cross-language.md) | 多语言序列化 | +| [代码生成](codegen.md) | 实验性的 AOT 代码生成 | +| [线程安全](thread-safety.md) | 并发使用模式 | +| [故障排查](troubleshooting.md) | 常见问题与解决方案 | ## 相关资源 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/go/struct-tags.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/go/struct-tags.md index 4579a1d744..a62b32770a 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/go/struct-tags.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/go/struct-tags.md @@ -19,14 +19,11 @@ license: | limitations under the License. --- -> 中文导读:本页介绍字段级序列化配置,包括字段 ID、可空控制、引用跟踪、忽略字段与动态类型控制等。 -> 建议在跨语言和兼容模式场景中优先显式配置字段 ID,并在需要时开启 ref/nullable 以保证行为一致。 - -Fory Go uses struct tags to customize field-level serialization behavior. This allows fine-grained control over how individual fields are serialized. +Fory Go 通过 struct tag 自定义字段级序列化行为,从而精细控制每个字段如何序列化。 ## 标签语法 -The general syntax for Fory struct tags: +Fory struct tag 的通用格式如下: ```go type MyStruct struct { @@ -34,13 +31,13 @@ type MyStruct struct { } ``` -Multiple options are separated by commas (`,`). +多个选项使用逗号(`,`)分隔。 ## 可用标签 ### 字段 ID -Use `id=N` to assign a numeric ID to a field for compact encoding: +使用 `id=N` 为字段分配数值 ID,以获得更紧凑编码: ```go type User struct { @@ -50,21 +47,21 @@ type User struct { } ``` -**Benefits**: +**收益:** -- Smaller serialized size (numeric IDs vs field names) -- Faster serialization/deserialization -- Required for optimal cross-language compatibility +- 序列化体积更小(数值 ID 替代字段名) +- 序列化/反序列化更快 +- 跨语言兼容场景下更推荐 -**Notes**: +**注意:** -- IDs must be unique within a struct -- IDs must be >= 0 -- If not specified, field name is used (larger payload) +- 同一 struct 内 ID 必须唯一 +- ID 必须 `>= 0` +- 未指定时使用字段名(payload 更大) ### 忽略字段 -Use `-` to exclude a field from serialization: +使用 `-` 将字段排除在序列化之外: ```go type User struct { @@ -74,11 +71,11 @@ type User struct { } ``` -The `Password` field will not be included in serialized output and will remain at its zero value after deserialization. +`Password` 不会进入序列化结果,反序列化后将保持该类型零值。 ### 可空控制 -Use `nullable` to control whether null flags are written for pointer fields: +使用 `nullable` 控制是否为指针字段写入 null 标记: ```go type Record struct { @@ -90,15 +87,15 @@ type Record struct { } ``` -**Notes**: +**注意:** -- Only applies to pointer, slice, and map fields -- When `nullable=false`, serializing a nil value will cause an error -- Default is `false` (no null flag written) +- 仅适用于指针、slice、map 字段 +- `nullable=false` 时,序列化 nil 会报错 +- 默认是 `false`(不写 null 标记) ### 引用跟踪 -Control per-field reference tracking for slices, maps, or pointer to struct fields: +可为 slice、map、或“指向 struct 的指针字段”设置字段级引用跟踪: ```go type Container struct { @@ -110,22 +107,22 @@ type Container struct { } ``` -**Notes**: +**注意:** -- Applies to slices, maps, and pointer to struct fields -- Pointer to primitive types (e.g., `*int`, `*string`) cannot use this tag -- Default is `ref=false` (no reference tracking) -- When global `WithTrackRef(false)` is set, field ref tags are ignored -- When global `WithTrackRef(true)` is set, use `ref=false` to disable for specific fields +- 适用于 slice、map 与“指向 struct 的指针字段” +- 指向原生类型的指针(如 `*int`、`*string`)不能使用该标签 +- 默认 `ref=false`(不开启引用跟踪) +- 全局 `WithTrackRef(false)` 时,字段级 ref 标签会被忽略 +- 全局 `WithTrackRef(true)` 时,可用 `ref=false` 对单字段禁用 -**Use cases**: +**适用场景:** -- Enable for fields that may be circular or shared -- Disable for fields that are always unique (optimization) +- 可能出现共享或循环引用的字段 +- 可明确唯一的字段可禁用(性能优化) -### Encoding +### 编码控制 -Use `encoding` to control how numeric fields are encoded: +使用 `encoding` 控制数值字段编码方式: ```go type Metrics struct { @@ -140,24 +137,24 @@ type Metrics struct { } ``` -**Supported encodings**: +**支持编码:** -| Type | Options | Default | +| 类型 | 可选值 | 默认值 | | -------- | --------------------------- | -------- | -| `int32` | `varint`, `fixed` | `varint` | -| `uint32` | `varint`, `fixed` | `varint` | -| `int64` | `varint`, `fixed`, `tagged` | `varint` | -| `uint64` | `varint`, `fixed`, `tagged` | `varint` | +| `int32` | `varint`、`fixed` | `varint` | +| `uint32` | `varint`、`fixed` | `varint` | +| `int64` | `varint`、`fixed`、`tagged` | `varint` | +| `uint64` | `varint`、`fixed`、`tagged` | `varint` | -**When to use**: +**何时使用:** -- `varint`: Best for values that are often small (default) -- `fixed`: Best for values that use full range (e.g., timestamps, hashes) -- `tagged`: When type information needs to be preserved +- `varint`:适合小值居多(默认) +- `fixed`:适合接近全值域分布(如时间戳、哈希) +- `tagged`:适合需保留类型信息的场景 -**Shorthand for int32/uint32**: +**int32/uint32 简写:** -Use `compress` as a convenience tag for int32/uint32 fields: +对 int32/uint32 字段可使用 `compress` 作为便捷标签: ```go type Data struct { @@ -166,9 +163,9 @@ type Data struct { } ``` -## Combining Tags +## 组合标签 -Multiple tags can be combined using comma separator: +多个标签可使用逗号组合: ```go type Document struct { @@ -178,9 +175,9 @@ type Document struct { } ``` -## Integration with Other Tags +## 与其他标签共存 -Fory tags coexist with other struct tags: +Fory 标签可与其他 struct tag 并存: ```go type User struct { @@ -190,11 +187,11 @@ type User struct { } ``` -Each tag namespace is independent. +各标签命名空间互不影响。 -## Field Visibility +## 字段可见性 -Only **exported fields** (starting with uppercase) are considered: +仅处理**导出字段**(首字母大写): ```go type User struct { @@ -204,26 +201,26 @@ type User struct { } ``` -Unexported fields are always ignored, regardless of tags. +未导出字段始终忽略,与是否配置 tag 无关。 -## Field Ordering +## 字段顺序 -Fields are serialized in a consistent order based on: +字段会按稳定顺序序列化,依据: -1. Field name (alphabetically in snake_case) -2. Field type +1. 字段名(snake_case 字典序) +2. 字段类型 -This ensures cross-language compatibility where field order matters. +这可保证跨语言场景下的字段顺序一致性。 -## Struct Hash +## Struct 哈希 -Fory computes a hash of struct fields for version checking: +Fory 会基于 struct 字段计算哈希用于版本校验: -- Hash includes field names and types -- Hash is written to serialized data -- Mismatch triggers `ErrKindHashMismatch` +- 哈希包含字段名与字段类型 +- 哈希会写入序列化数据 +- 不匹配会触发 `ErrKindHashMismatch` -Struct field changes affect the hash: +结构字段变更会影响哈希: ```go // These produce different hashes @@ -236,9 +233,9 @@ type V2 struct { } ``` -## Examples +## 示例 -### API Response Struct +### API 响应结构 ```go type APIResponse struct { @@ -249,7 +246,7 @@ type APIResponse struct { } ``` -### Caching with Shared References +### 带共享引用的缓存结构 ```go type CacheEntry struct { @@ -260,7 +257,7 @@ type CacheEntry struct { } ``` -### Document with Circular References +### 带循环引用的文档结构 ```go type Document struct { @@ -271,9 +268,9 @@ type Document struct { } ``` -## Tag Parsing Errors +## 标签解析错误 -Invalid tags produce errors during registration: +注册阶段若标签非法会报错: ```go type BadStruct struct { @@ -287,15 +284,15 @@ err := f.RegisterStruct(BadStruct{}, 1) ## 最佳实践 -1. **Use `-` for sensitive data**: Passwords, tokens, internal state -2. **Enable ref tracking for shared objects**: When the same pointer appears multiple times -3. **Disable ref tracking for simple fields**: Optimization when you know the field is unique -4. **Keep names consistent**: Cross-language names should match -5. **Document tag usage**: Especially for non-obvious configurations +1. **敏感字段使用 `-`**:如密码、令牌、内部状态 +2. **共享对象启用 ref**:同一指针可能多次出现时开启 +3. **简单唯一字段禁用 ref**:可做性能优化 +4. **保持命名一致**:跨语言字段名应保持稳定 +5. **记录标签意图**:非显式配置建议补充注释说明 -## Common Patterns +## 常见模式 -### Ignoring Computed Fields +### 忽略计算字段 ```go type Rectangle struct { @@ -309,7 +306,7 @@ func (r *Rectangle) ComputeArea() { } ``` -### Circular Structure with Parent +### 带父指针的循环结构 ```go type TreeNode struct { @@ -319,7 +316,7 @@ type TreeNode struct { } ``` -### Mixed Serialization Needs +### 混合序列化需求 ```go type Session struct { @@ -333,6 +330,6 @@ type Session struct { ## 相关主题 -- [References](references.md) -- [Basic Serialization](basic-serialization.md) -- [Schema Evolution](schema-evolution.md) +- [引用](references.md) +- [基础序列化](basic-serialization.md) +- [Schema 演进](schema-evolution.md) diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/java/field-configuration.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/java/field-configuration.md index 0182eeb129..2f21ab6c69 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/java/field-configuration.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/java/field-configuration.md @@ -19,31 +19,28 @@ license: | limitations under the License. --- -> 中文导读:本页介绍字段级序列化配置,包括字段 ID、可空控制、引用跟踪、忽略字段与动态类型控制等。 -> 建议在跨语言和兼容模式场景中优先显式配置字段 ID,并在需要时开启 ref/nullable 以保证行为一致。 - 本页说明如何在 Java 中配置序列化字段级元信息。 ## 概述 Apache ForyTM 通过注解提供字段级配置: -- **`@ForyField`**: Configure field metadata (id, nullable, ref, dynamic) -- **`@Ignore`**: Exclude fields from serialization -- **Integer type annotations**: Control integer encoding (varint, fixed, tagged, unsigned) +- **`@ForyField`**:配置字段元信息(id、nullable、ref、dynamic) +- **`@Ignore`**:将字段排除在序列化之外 +- **整数类型注解**:控制整数编码方式(varint、fixed、tagged、unsigned) -This enables: +这些能力可用于: -- **Tag IDs**: Assign compact numeric IDs to reduce struct field meta size overhead for compatible mode -- **Nullability**: Control whether fields can be null -- **Reference Tracking**: Enable reference tracking for shared objects -- **Field Skipping**: Exclude fields from serialization -- **Encoding Control**: Specify how integers are encoded -- **Polymorphism Control**: Control type info writing for struct fields +- **Tag ID**:为兼容模式分配紧凑数值 ID,降低 struct 字段元信息开销 +- **可空控制**:声明字段是否允许为 null +- **引用跟踪**:为共享对象开启引用跟踪 +- **字段跳过**:显式排除不需要序列化的字段 +- **编码控制**:指定整数序列化编码策略 +- **多态控制**:控制 struct 字段是否写入运行时类型信息 ## 基本语法 -Use annotations on fields: +在字段上使用注解: ```java import org.apache.fory.annotation.ForyField; @@ -60,9 +57,9 @@ public class Person { } ``` -## The `@ForyField` Annotation +## `@ForyField` 注解 -Use `@ForyField` to configure field-level metadata: +使用 `@ForyField` 配置字段级元信息: ```java public class User { @@ -85,16 +82,16 @@ public class User { ### 参数 -| Parameter | Type | Default | Description | +| 参数 | 类型 | 默认值 | 说明 | | ---------- | --------- | ------- | -------------------------------------- | -| `id` | `int` | `-1` | Field tag ID (-1 = use field name) | -| `nullable` | `boolean` | `false` | Whether the field can be null | -| `ref` | `boolean` | `false` | Enable reference tracking | -| `dynamic` | `Dynamic` | `AUTO` | Control polymorphism for struct fields | +| `id` | `int` | `-1` | 字段 tag ID(`-1` 表示使用字段名编码) | +| `nullable` | `boolean` | `false` | 字段是否可为 null | +| `ref` | `boolean` | `false` | 是否开启引用跟踪 | +| `dynamic` | `Dynamic` | `AUTO` | 控制 struct 字段多态行为 | -## Field ID (`id`) +## 字段 ID(`id`) -Assigns a numeric ID to a field to minimize struct field meta size overhead for compatible mode: +通过为字段分配数值 ID,可降低兼容模式下 struct 字段元信息开销: ```java public class User { @@ -109,21 +106,21 @@ public class User { } ``` -**Benefits**: +**收益:** -- Smaller serialized size (numeric IDs vs field names in metadata) -- Reduced struct field meta overhead -- Allows renaming fields without breaking binary compatibility +- 序列化体积更小(元信息里用数值 ID 而不是字段名) +- struct 字段元信息开销更低 +- 可在不破坏二进制兼容性的前提下重命名字段 -**Recommendation**: It is recommended to configure field IDs for compatible mode since it reduces serialization cost. +**建议:** 兼容模式下建议配置字段 ID,以降低序列化成本。 -**Notes**: +**注意:** -- IDs must be unique within a class -- IDs must be >= 0 (use -1 to use field name encoding, which is the default) -- If not specified, field name is used in metadata (larger overhead) +- 同一个类内 ID 必须唯一 +- ID 必须 `>= 0`(`-1` 表示使用字段名编码,也是默认行为) +- 未指定时,元信息将写字段名(开销更大) -**Without field IDs** (field names used in metadata): +**不配置字段 ID**(元信息使用字段名)示例: ```java public class User { @@ -132,39 +129,39 @@ public class User { } ``` -## Nullable Fields (`nullable`) +## 可空字段(`nullable`) -Use `nullable = true` for fields that can be `null`: +对可能为 `null` 的字段使用 `nullable = true`: ```java public class Record { - // Nullable string field + // 可空字符串字段 @ForyField(id = 0, nullable = true) private String optionalName; - // Nullable Integer field (boxed type) + // 可空 Integer 字段(装箱类型) @ForyField(id = 1, nullable = true) private Integer optionalCount; - // Non-nullable field (default) + // 非可空字段(默认) @ForyField(id = 2) private String requiredName; } ``` -**Notes**: +**注意:** -- Default is `nullable = false` (non-nullable) -- When `nullable = false`, Fory skips writing the null flag (saves 1 byte) -- Boxed types (`Integer`, `Long`, etc.) that can be null should use `nullable = true` +- 默认是 `nullable = false`(不可空) +- `nullable = false` 时,Fory 会省略 null 标记写入(节省 1 字节) +- 可能为 null 的装箱类型(`Integer`、`Long` 等)建议显式设为 `nullable = true` -## Reference Tracking (`ref`) +## 引用跟踪(`ref`) -Enable reference tracking for fields that may be shared or circular: +对于可能共享或循环引用的字段,启用引用跟踪: ```java public class RefOuter { - // Both fields may point to the same inner object + // 两个字段可能指向同一个内部对象 @ForyField(id = 0, ref = true, nullable = true) private RefInner inner1; @@ -176,56 +173,56 @@ public class CircularRef { @ForyField(id = 0) private String name; - // Self-referencing field for circular references + // 自引用字段,用于循环引用 @ForyField(id = 1, ref = true, nullable = true) private CircularRef selfRef; } ``` -**Use Cases**: +**适用场景:** -- Enable for fields that may be circular or shared -- When the same object is referenced from multiple fields +- 字段可能形成循环或共享关系 +- 同一对象被多个字段引用 -**Notes**: +**注意:** -- Default is `ref = false` (no reference tracking) -- When `ref = false`, avoids IdentityMap overhead and skips ref tracking flag -- Reference tracking only takes effect when global ref tracking is enabled +- 默认是 `ref = false`(不跟踪引用) +- `ref = false` 可避免 IdentityMap 开销,也会跳过引用跟踪标记 +- 仅在全局启用 ref tracking 时,字段级 ref 才生效 -## Dynamic (Polymorphism Control) +## Dynamic(多态控制) -Controls polymorphism behavior for struct fields in cross-language serialization: +控制跨语言序列化时 struct 字段的多态行为: ```java public class Container { - // AUTO: Interface/abstract types are dynamic, concrete types are not + // AUTO:接口/抽象类型动态,具体类型非动态 @ForyField(id = 0, dynamic = ForyField.Dynamic.AUTO) - private Animal animal; // Interface - type info written + private Animal animal; // 接口类型,写入类型信息 - // FALSE: No type info written, uses declared type's serializer + // FALSE:不写类型信息,直接按声明类型序列化 @ForyField(id = 1, dynamic = ForyField.Dynamic.FALSE) - private Dog dog; // Concrete - no type info + private Dog dog; // 具体类型,不写类型信息 - // TRUE: Type info written to support runtime subtypes + // TRUE:写类型信息,支持运行时子类型 @ForyField(id = 2, dynamic = ForyField.Dynamic.TRUE) - private Object data; // Force polymorphic + private Object data; // 强制多态 } ``` -**Options**: +**取值:** -| Value | Description | -| ------- | ------------------------------------------------------------------- | -| `AUTO` | Auto-detect: interface/abstract are dynamic, concrete types are not | -| `FALSE` | No type info written, uses declared type's serializer directly | -| `TRUE` | Type info written to support subtypes at runtime | +| 值 | 说明 | +| ------- | ------------------------------------------- | +| `AUTO` | 自动判断:接口/抽象类型动态,具体类型非动态 | +| `FALSE` | 不写类型信息,直接使用声明类型的序列化器 | +| `TRUE` | 写入类型信息,以支持运行时子类型 | -## Skipping Fields +## 跳过字段 -### Using `@Ignore` +### 使用 `@Ignore` -Exclude fields from serialization: +将字段排除在序列化之外: ```java import org.apache.fory.annotation.Ignore; @@ -238,69 +235,69 @@ public class User { private String name; @Ignore - private String password; // Not serialized + private String password; // 不序列化 @Ignore - private Object internalState; // Not serialized + private Object internalState; // 不序列化 } ``` -### Using `transient` +### 使用 `transient` -Java's `transient` keyword also excludes fields: +Java 的 `transient` 关键字同样会排除字段: ```java public class User { @ForyField(id = 0) private long id; - private transient String password; // Not serialized - private transient Object cache; // Not serialized + private transient String password; // 不序列化 + private transient Object cache; // 不序列化 } ``` -## Integer Type Annotations +## 整数类型注解 -Fory provides annotations to control integer encoding for cross-language compatibility. +Fory 提供整数注解,用于在跨语言场景中控制编码方式。 -### Signed 32-bit Integer (`@Int32Type`) +### 有符号 32 位整数(`@Int32Type`) ```java import org.apache.fory.annotation.Int32Type; public class MyStruct { - // Variable-length encoding (default) - compact for small values + // 变长编码(默认),小值更紧凑 @Int32Type(compress = true) private int compactId; - // Fixed 4-byte encoding - consistent size + // 固定 4 字节编码,长度稳定 @Int32Type(compress = false) private int fixedId; } ``` -### Signed 64-bit Integer (`@Int64Type`) +### 有符号 64 位整数(`@Int64Type`) ```java import org.apache.fory.annotation.Int64Type; import org.apache.fory.config.LongEncoding; public class MyStruct { - // Variable-length encoding (default) + // 变长编码(默认) @Int64Type(encoding = LongEncoding.VARINT) private long compactId; - // Fixed 8-byte encoding + // 固定 8 字节编码 @Int64Type(encoding = LongEncoding.FIXED) private long fixedTimestamp; - // Tagged encoding (4 bytes for small values, 9 bytes otherwise) + // tagged 编码(小值 4 字节,否则 9 字节) @Int64Type(encoding = LongEncoding.TAGGED) private long taggedValue; } ``` -### Unsigned Integers +### 无符号整数 ```java import org.apache.fory.annotation.Uint8Type; @@ -310,23 +307,23 @@ import org.apache.fory.annotation.Uint64Type; import org.apache.fory.config.LongEncoding; public class UnsignedStruct { - // Unsigned 8-bit [0, 255] + // 无符号 8 位 [0, 255] @Uint8Type private short flags; - // Unsigned 16-bit [0, 65535] + // 无符号 16 位 [0, 65535] @Uint16Type private int port; - // Unsigned 32-bit with varint encoding (default) + // 无符号 32 位,varint 编码(默认) @Uint32Type(compress = true) private long compactCount; - // Unsigned 32-bit with fixed encoding + // 无符号 32 位,fixed 编码 @Uint32Type(compress = false) private long fixedCount; - // Unsigned 64-bit with various encodings + // 无符号 64 位,多种编码 @Uint64Type(encoding = LongEncoding.VARINT) private long varintU64; @@ -338,31 +335,31 @@ public class UnsignedStruct { } ``` -### Encoding Summary +### 编码汇总 -| Annotation | Type ID | Encoding | Size | -| -------------------------------- | ------- | -------- | ------------ | -| `@Int32Type(compress = true)` | 5 | varint | 1-5 bytes | -| `@Int32Type(compress = false)` | 4 | fixed | 4 bytes | -| `@Int64Type(encoding = VARINT)` | 7 | varint | 1-10 bytes | -| `@Int64Type(encoding = FIXED)` | 6 | fixed | 8 bytes | -| `@Int64Type(encoding = TAGGED)` | 8 | tagged | 4 or 9 bytes | -| `@Uint8Type` | 9 | fixed | 1 byte | -| `@Uint16Type` | 10 | fixed | 2 bytes | -| `@Uint32Type(compress = true)` | 12 | varint | 1-5 bytes | -| `@Uint32Type(compress = false)` | 11 | fixed | 4 bytes | -| `@Uint64Type(encoding = VARINT)` | 14 | varint | 1-10 bytes | -| `@Uint64Type(encoding = FIXED)` | 13 | fixed | 8 bytes | -| `@Uint64Type(encoding = TAGGED)` | 15 | tagged | 4 or 9 bytes | +| 注解 | Type ID | 编码 | 大小 | +| -------------------------------- | ------- | ------ | ----------- | +| `@Int32Type(compress = true)` | 5 | varint | 1-5 字节 | +| `@Int32Type(compress = false)` | 4 | fixed | 4 字节 | +| `@Int64Type(encoding = VARINT)` | 7 | varint | 1-10 字节 | +| `@Int64Type(encoding = FIXED)` | 6 | fixed | 8 字节 | +| `@Int64Type(encoding = TAGGED)` | 8 | tagged | 4 或 9 字节 | +| `@Uint8Type` | 9 | fixed | 1 字节 | +| `@Uint16Type` | 10 | fixed | 2 字节 | +| `@Uint32Type(compress = true)` | 12 | varint | 1-5 字节 | +| `@Uint32Type(compress = false)` | 11 | fixed | 4 字节 | +| `@Uint64Type(encoding = VARINT)` | 14 | varint | 1-10 字节 | +| `@Uint64Type(encoding = FIXED)` | 13 | fixed | 8 字节 | +| `@Uint64Type(encoding = TAGGED)` | 15 | tagged | 4 或 9 字节 | -**When to Use**: +**何时使用:** -- `varint`: Best for values that are often small (default) -- `fixed`: Best for values that use full range (e.g., timestamps, hashes) -- `tagged`: Good balance between size and performance -- Unsigned types: For cross-language compatibility with Rust, Go, C++ +- `varint`:数值通常较小时最优(默认) +- `fixed`:数值分布接近全范围时更稳定(如时间戳、哈希) +- `tagged`:在体积与性能间平衡较好 +- 无符号类型:适合与 Rust/Go/C++ 等语言进行无符号整数互操作 -## Complete Example +## 完整示例 ```java import org.apache.fory.Fory; @@ -377,18 +374,18 @@ import java.util.Map; import java.util.Set; public class Document { - // Fields with tag IDs (recommended for compatible mode) + // 带 tag ID 的字段(兼容模式推荐) @ForyField(id = 0) private String title; @ForyField(id = 1) private int version; - // Nullable field + // 可空字段 @ForyField(id = 2, nullable = true) private String description; - // Collection fields + // 集合字段 @ForyField(id = 3) private List tags; @@ -398,24 +395,24 @@ public class Document { @ForyField(id = 5) private Set categories; - // Integer with different encodings + // 不同编码方式的整数 @ForyField(id = 6) @Uint64Type(encoding = LongEncoding.VARINT) - private long viewCount; // varint encoding + private long viewCount; // varint 编码 @ForyField(id = 7) @Uint64Type(encoding = LongEncoding.FIXED) - private long fileSize; // fixed encoding + private long fileSize; // fixed 编码 @ForyField(id = 8) @Uint64Type(encoding = LongEncoding.TAGGED) - private long checksum; // tagged encoding + private long checksum; // tagged 编码 - // Reference-tracked field for shared/circular references + // 共享/循环引用字段 @ForyField(id = 9, ref = true, nullable = true) private Document parent; - // Ignored field (not serialized) + // 忽略字段(不序列化) private transient Object cache; // Getters and setters... @@ -446,13 +443,13 @@ public class Main { } ``` -## Cross-Language Compatibility +## 跨语言兼容 -When serializing data to be read by other languages (Python, Rust, C++, Go), use field IDs and matching type annotations: +当数据需要被其他语言(Python、Rust、C++、Go)读取时,建议使用字段 ID 并配套类型注解: ```java public class CrossLangData { - // Use field IDs for cross-language compatibility + // 使用字段 ID 保证跨语言兼容 @ForyField(id = 0) @Int32Type(compress = true) private int intVar; @@ -470,9 +467,9 @@ public class CrossLangData { } ``` -## Schema Evolution +## Schema 演进 -Compatible mode supports schema evolution. It is recommended to configure field IDs to reduce serialization cost: +兼容模式支持 Schema 演进。建议配置字段 ID 以降低序列化成本: ```java // Version 1 @@ -497,9 +494,9 @@ public class DataV2 { } ``` -Data serialized with V1 can be deserialized with V2 (new field will be `null`). +V1 写入的数据可由 V2 读取(新增字段会是 `null`)。 -Alternatively, field IDs can be omitted (field names will be used in metadata with larger overhead): +也可以不配置字段 ID(元信息会使用字段名,开销更大): ```java public class Data { @@ -508,23 +505,23 @@ public class Data { } ``` -## Native Mode vs Xlang Mode +## Native 模式与 Xlang 模式 -Field configuration behaves differently depending on the serialization mode: +字段配置在不同序列化模式下的默认行为不同。 -### Native Mode (Java-only) +### Native 模式(仅 Java) -Native mode has **relaxed default values** for maximum compatibility: +Native 模式以最大兼容性为目标,默认值更宽松: -- **Nullable**: Reference types are nullable by default -- **Ref tracking**: Enabled by default for object references (except `String`, boxed types, and time types) -- **Polymorphism**: All non-final classes support polymorphism by default +- **Nullable**:引用类型默认可空 +- **Ref tracking**:对象引用默认开启(`String`、装箱类型、时间类型除外) +- **Polymorphism**:所有非 final 类默认支持多态 -In native mode, you typically **don't need to configure field annotations** unless you want to: +在 Native 模式下,通常**不需要额外字段注解**,除非你希望: -- Reduce serialized size by using field IDs -- Optimize performance by disabling unnecessary ref tracking -- Control integer encoding for specific fields +- 用字段 ID 降低体积 +- 关闭不必要的 ref 跟踪以优化性能 +- 对特定字段精确控制整数编码 ```java // Native mode: works without any annotations @@ -535,20 +532,20 @@ public class User { } ``` -### Xlang Mode (Cross-language) +### Xlang 模式(跨语言) -Xlang mode has **stricter default values** due to type system differences between languages: +由于不同语言类型系统差异,Xlang 模式默认值更严格: -- **Nullable**: Fields are non-nullable by default (`nullable = false`) -- **Ref tracking**: Disabled by default (`ref = false`) -- **Polymorphism**: Concrete types are non-polymorphic by default +- **Nullable**:字段默认不可空(`nullable = false`) +- **Ref tracking**:默认关闭(`ref = false`) +- **Polymorphism**:具体类型默认不写多态类型信息 -In xlang mode, you **need to configure fields** when: +在 Xlang 模式下,以下情况需要显式配置: -- A field can be null (use `nullable = true`) -- A field needs reference tracking for shared/circular objects (use `ref = true`) -- Integer types need specific encoding for cross-language compatibility -- You want to reduce metadata size (use field IDs) +- 字段可能为 null(使用 `nullable = true`) +- 字段需要共享/循环引用语义(使用 `ref = true`) +- 整数类型需要为跨语言兼容指定编码 +- 你希望减少元信息大小(使用字段 ID) ```java // Xlang mode: explicit configuration required for nullable/ref fields @@ -567,42 +564,42 @@ public class User { } ``` -### Default Values Summary - -| Option | Native Mode Default | Xlang Mode Default | -| ---------- | ------------------------ | --------------------------------- | -| `nullable` | `true` (reference types) | `false` | -| `ref` | `true` | `false` | -| `dynamic` | `true` (non-final) | `AUTO` (concrete types are final) | - -## Best Practices - -1. **Configure field IDs**: Recommended for compatible mode to reduce serialization cost -2. **Use `nullable = true` for nullable fields**: Required for fields that can be null -3. **Enable ref tracking for shared objects**: Use `ref = true` when objects are shared or circular -4. **Use `@Ignore` or `transient` for sensitive data**: Passwords, tokens, internal state -5. **Choose appropriate encoding**: `varint` for small values, `fixed` for full-range values -6. **Keep IDs stable**: Once assigned, don't change field IDs -7. **Configure unsigned types for cross-language compatibility**: When interoperating with unsigned numbers in Rust, Go, C++ - -## Annotations Reference - -| Annotation | Description | -| ----------------------------- | -------------------------------------- | -| `@ForyField(id = N)` | Field tag ID to reduce metadata size | -| `@ForyField(nullable = true)` | Mark field as nullable | -| `@ForyField(ref = true)` | Enable reference tracking | -| `@ForyField(dynamic = ...)` | Control polymorphism for struct fields | -| `@Ignore` | Exclude field from serialization | -| `@Int32Type(compress = ...)` | 32-bit signed integer encoding | -| `@Int64Type(encoding = ...)` | 64-bit signed integer encoding | -| `@Uint8Type` | Unsigned 8-bit integer | -| `@Uint16Type` | Unsigned 16-bit integer | -| `@Uint32Type(compress = ...)` | Unsigned 32-bit integer encoding | -| `@Uint64Type(encoding = ...)` | Unsigned 64-bit integer encoding | - -## Related Topics - -- [Basic Serialization](basic_serialization) - Getting started with Fory serialization -- [Schema Evolution](schema_evolution) - Compatible mode and schema evolution -- [Cross-Language](cross_language) - Interoperability with Python, Rust, C++, Go +### 默认值汇总 + +| 选项 | Native 模式默认值 | Xlang 模式默认值 | +| ---------- | --------------------- | ---------------------------------- | +| `nullable` | `true`(引用类型) | `false` | +| `ref` | `true` | `false` | +| `dynamic` | `true`(非 final 类) | `AUTO`(具体类型通常按非动态处理) | + +## 最佳实践 + +1. **配置字段 ID**:兼容模式下建议配置,降低序列化成本 +2. **可空字段使用 `nullable = true`**:对可为 null 的字段必须显式声明 +3. **共享对象开启 `ref`**:对象共享或循环时使用 `ref = true` +4. **敏感字段用 `@Ignore` 或 `transient`**:如密码、令牌、内部状态 +5. **选择合适编码**:小值用 `varint`,全范围值用 `fixed` +6. **保持 ID 稳定**:一旦分配,不要随意改动字段 ID +7. **跨语言场景显式无符号类型**:与 Rust、Go、C++ 互操作时尤其重要 + +## 注解速查 + +| 注解 | 说明 | +| ----------------------------- | ------------------------------- | +| `@ForyField(id = N)` | 配置字段 tag ID,减少元信息开销 | +| `@ForyField(nullable = true)` | 将字段标记为可空 | +| `@ForyField(ref = true)` | 为字段启用引用跟踪 | +| `@ForyField(dynamic = ...)` | 控制 struct 字段多态行为 | +| `@Ignore` | 将字段排除在序列化之外 | +| `@Int32Type(compress = ...)` | 32 位有符号整数编码 | +| `@Int64Type(encoding = ...)` | 64 位有符号整数编码 | +| `@Uint8Type` | 8 位无符号整数 | +| `@Uint16Type` | 16 位无符号整数 | +| `@Uint32Type(compress = ...)` | 32 位无符号整数编码 | +| `@Uint64Type(encoding = ...)` | 64 位无符号整数编码 | + +## 相关主题 + +- [基础序列化](basic_serialization) - 快速上手 Fory 序列化 +- [Schema 演进](schema_evolution) - 兼容模式与 schema 演进 +- [跨语言](cross_language) - 与 Python、Rust、C++、Go 互操作 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/python/field-configuration.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/python/field-configuration.md index fb489d283b..65d7b04281 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/python/field-configuration.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/python/field-configuration.md @@ -19,31 +19,28 @@ license: | limitations under the License. --- -> 中文导读:本页介绍字段级序列化配置,包括字段 ID、可空控制、引用跟踪、忽略字段与动态类型控制等。 -> 建议在跨语言和兼容模式场景中优先显式配置字段 ID,并在需要时开启 ref/nullable 以保证行为一致。 - 本页说明如何在 Python 中配置序列化字段级元信息。 ## 概述 -Apache ForyTM 通过以下方式提供字段级配置: +Apache ForyTM 通过以下机制提供字段级配置: -- **`pyfory.field()`**: Configure field metadata (id, nullable, ref, ignore, dynamic) -- **Type annotations**: Control integer encoding (varint, fixed, tagged) -- **`Optional[T]`**: Mark fields as nullable +- **`pyfory.field()`**:配置字段元信息(id、nullable、ref、ignore、dynamic) +- **类型注解**:控制整数编码(varint、fixed、tagged) +- **`Optional[T]`**:标记字段可空 -This enables: +这些能力可用于: -- **Tag IDs**: Assign compact numeric IDs to reduce struct field meta size overhead -- **Nullability**: Control whether fields can be null -- **Reference Tracking**: Enable reference tracking for shared objects -- **Field Skipping**: Exclude fields from serialization -- **Encoding Control**: Specify how integers are encoded (varint, fixed, tagged) -- **Polymorphism**: Control whether type info is written for struct fields +- **Tag ID**:分配紧凑数值 ID,降低 struct 字段元信息开销 +- **可空控制**:声明字段是否可为 null/None +- **引用跟踪**:为共享对象启用引用跟踪 +- **字段跳过**:从序列化中排除字段 +- **编码控制**:指定整数编码方式(varint、fixed、tagged) +- **多态控制**:控制 struct 字段是否写入类型信息 ## 基本语法 -Use `@dataclass` decorator with type annotations and `pyfory.field()`: +结合 `@dataclass`、类型注解与 `pyfory.field()`: ```python from dataclasses import dataclass @@ -59,7 +56,7 @@ class Person: ## `pyfory.field()` 函数 -Use `pyfory.field()` to configure field-level metadata: +使用 `pyfory.field()` 配置字段级元信息: ```python @dataclass @@ -73,19 +70,19 @@ class User: ### 参数 -| Parameter | Type | Default | Description | -| ----------------- | -------- | --------- | ------------------------------------ | -| `id` | `int` | `-1` | Field tag ID (-1 = use field name) | -| `nullable` | `bool` | `False` | Whether the field can be null | -| `ref` | `bool` | `False` | Enable reference tracking | -| `ignore` | `bool` | `False` | Exclude field from serialization | -| `dynamic` | `bool` | `None` | Control whether type info is written | -| `default` | Any | `MISSING` | Default value for the field | -| `default_factory` | Callable | `MISSING` | Factory function for default value | +| 参数 | 类型 | 默认值 | 说明 | +| ----------------- | -------- | --------- | ---------------------------------- | +| `id` | `int` | `-1` | 字段 tag ID(`-1` 表示使用字段名) | +| `nullable` | `bool` | `False` | 字段是否可为 null/None | +| `ref` | `bool` | `False` | 是否启用引用跟踪 | +| `ignore` | `bool` | `False` | 是否从序列化中排除 | +| `dynamic` | `bool` | `None` | 控制是否写入类型信息 | +| `default` | Any | `MISSING` | 字段默认值 | +| `default_factory` | Callable | `MISSING` | 默认值工厂函数 | -## Field ID (`id`) +## 字段 ID(`id`) -Assigns a numeric ID to a field to minimize struct field meta size overhead: +通过给字段分配数值 ID,可减少 struct 字段元信息开销: ```python @dataclass @@ -95,21 +92,21 @@ class User: age: pyfory.int32 = pyfory.field(id=2, default=0) ``` -**Benefits**: +**收益:** -- Smaller serialized size (numeric IDs vs field names in metadata) -- Reduced struct field meta overhead -- Allows renaming fields without breaking binary compatibility +- 序列化体积更小(元信息中数值 ID 替代字段名) +- struct 字段元信息开销更低 +- 字段重命名时可保持二进制兼容 -**Recommendation**: It is recommended to configure field IDs for compatible mode since it reduces serialization cost. +**建议:** 兼容模式下建议配置字段 ID,以降低序列化成本。 -**Notes**: +**注意:** -- IDs must be unique within a class -- IDs must be >= 0 (use -1 to use field name encoding, which is the default) -- If not specified, field name is used in metadata (larger overhead) +- 同一类内 ID 必须唯一 +- ID 必须 `>= 0`(`-1` 表示使用字段名编码,默认行为) +- 未指定时会使用字段名写入元信息(开销更大) -**Without field IDs** (field names used in metadata): +**不配置字段 ID**(元信息使用字段名)示例: ```python @dataclass @@ -118,35 +115,35 @@ class User: name: str = "" ``` -## Nullable Fields (`nullable`) +## 可空字段(`nullable`) -Use `nullable=True` for fields that can be `None`: +对可能为 `None` 的字段使用 `nullable=True`: ```python from typing import Optional @dataclass class Record: - # Nullable string field + # 可空字符串字段 optional_name: Optional[str] = pyfory.field(id=0, nullable=True, default=None) - # Nullable integer field + # 可空整数字段 optional_count: Optional[pyfory.int32] = pyfory.field(id=1, nullable=True, default=None) ``` -**Notes**: +**注意:** -- `Optional[T]` fields must have `nullable=True` -- Non-optional fields default to `nullable=False` +- `Optional[T]` 字段应配合 `nullable=True` +- 非 Optional 字段默认 `nullable=False` -## Reference Tracking (`ref`) +## 引用跟踪(`ref`) -Enable reference tracking for fields that may be shared or circular: +对于可能共享或循环引用的字段启用引用跟踪: ```python @dataclass class RefOuter: - # Both fields may point to the same inner object + # 两个字段可能指向同一个内部对象 inner1: Optional[RefInner] = pyfory.field(id=0, ref=True, nullable=True, default=None) inner2: Optional[RefInner] = pyfory.field(id=1, ref=True, nullable=True, default=None) @@ -154,37 +151,37 @@ class RefOuter: @dataclass class CircularRef: name: str = pyfory.field(id=0, default="") - # Self-referencing field for circular references + # 自引用字段,用于循环引用 self_ref: Optional["CircularRef"] = pyfory.field(id=1, ref=True, nullable=True, default=None) ``` -**Use Cases**: +**适用场景:** -- Enable for fields that may be circular or shared -- When the same object is referenced from multiple fields +- 字段可能形成循环或共享关系 +- 同一对象被多个字段引用 -**Notes**: +**注意:** -- Reference tracking only takes effect when `Fory(ref=True)` is set globally -- Field-level `ref=True` AND global `ref=True` must both be enabled +- 只有全局设置 `Fory(ref=True)` 时,引用跟踪才生效 +- 字段级 `ref=True` 与全局 `ref=True` 必须同时开启 -## Skipping Fields (`ignore`) +## 跳过字段(`ignore`) -Exclude fields from serialization: +将字段排除在序列化之外: ```python @dataclass class User: id: pyfory.int64 = pyfory.field(id=0, default=0) name: str = pyfory.field(id=1, default="") - # Not serialized + # 不序列化 _cache: dict = pyfory.field(ignore=True, default_factory=dict) _internal_state: str = pyfory.field(ignore=True, default="") ``` -## Dynamic Fields (`dynamic`) +## Dynamic 字段(`dynamic`) -Control whether type information is written for struct fields. This is essential for polymorphism support: +控制 struct 字段是否写入类型信息,这是支持多态的关键: ```python from abc import ABC, abstractmethod @@ -203,36 +200,36 @@ class Circle(Shape): @dataclass class Container: - # Abstract class: dynamic is always True (type info written) + # 抽象类:dynamic 总为 True(写类型信息) shape: Shape = pyfory.field(id=0) - # Force type info for concrete type (support runtime subtypes) + # 对具体类型强制写类型信息(支持运行时子类) circle: Circle = pyfory.field(id=1, dynamic=True) - # Skip type info for concrete type (use declared type directly) + # 对具体类型跳过类型信息(按声明类型处理) fixed_circle: Circle = pyfory.field(id=2, dynamic=False) ``` -**Default Behavior**: +**默认行为:** -| Mode | Abstract Class | Concrete Object Types | Numeric/str/time Types | -| ----------- | -------------- | --------------------- | ---------------------- | -| Native mode | `True` | `True` | `False` | -| Xlang mode | `True` | `False` | `False` | +| 模式 | 抽象类 | 具体对象类型 | 数值/str/time 类型 | +| ----------- | ------ | ------------ | ------------------ | +| Native 模式 | `True` | `True` | `False` | +| Xlang 模式 | `True` | `False` | `False` | -**Notes**: +**注意:** -- **Abstract classes**: `dynamic` is always `True` (type info must be written) -- **Native mode**: `dynamic` defaults to `True` for object types, `False` for numeric/str/time types -- **Xlang mode**: `dynamic` defaults to `False` for concrete types -- Use `dynamic=True` when a concrete field may hold subclass instances -- Use `dynamic=False` for performance optimization when type is known +- **抽象类**:`dynamic` 始终为 `True`(必须写类型信息) +- **Native 模式**:对象类型默认 `dynamic=True`;数值/str/time 默认 `False` +- **Xlang 模式**:具体类型默认 `dynamic=False` +- 当具体字段可能持有子类实例时,使用 `dynamic=True` +- 当类型固定且追求性能时,可使用 `dynamic=False` -## Integer Type Annotations +## 整数类型注解 -Fory provides type annotations to control integer encoding: +Fory 提供类型注解来控制整数编码。 -### Signed Integers +### 有符号整数 ```python @dataclass @@ -243,7 +240,7 @@ class SignedIntegers: long_val: pyfory.int64 = 0 # 64-bit signed (varint encoding) ``` -### Unsigned Integers +### 无符号整数 ```python @dataclass @@ -264,7 +261,7 @@ class UnsignedIntegers: u64_tagged: pyfory.tagged_uint64 = 0 # 64-bit unsigned (tagged) ``` -### Floating Point +### 浮点数 ```python @dataclass @@ -273,31 +270,31 @@ class FloatingPoint: double_val: pyfory.float64 = 0.0 # 64-bit double ``` -### Encoding Summary +### 编码汇总 -| Type | Encoding | Size | -| ---------------------- | -------- | ---------- | -| `pyfory.int8` | fixed | 1 byte | -| `pyfory.int16` | fixed | 2 bytes | -| `pyfory.int32` | varint | 1-5 bytes | -| `pyfory.int64` | varint | 1-10 bytes | -| `pyfory.uint8` | fixed | 1 byte | -| `pyfory.uint16` | fixed | 2 bytes | -| `pyfory.uint32` | varint | 1-5 bytes | -| `pyfory.uint64` | varint | 1-10 bytes | -| `pyfory.fixed_uint32` | fixed | 4 bytes | -| `pyfory.fixed_uint64` | fixed | 8 bytes | -| `pyfory.tagged_uint64` | tagged | 1-9 bytes | -| `pyfory.float32` | fixed | 4 bytes | -| `pyfory.float64` | fixed | 8 bytes | +| 类型 | 编码 | 大小 | +| ---------------------- | ------ | --------- | +| `pyfory.int8` | fixed | 1 字节 | +| `pyfory.int16` | fixed | 2 字节 | +| `pyfory.int32` | varint | 1-5 字节 | +| `pyfory.int64` | varint | 1-10 字节 | +| `pyfory.uint8` | fixed | 1 字节 | +| `pyfory.uint16` | fixed | 2 字节 | +| `pyfory.uint32` | varint | 1-5 字节 | +| `pyfory.uint64` | varint | 1-10 字节 | +| `pyfory.fixed_uint32` | fixed | 4 字节 | +| `pyfory.fixed_uint64` | fixed | 8 字节 | +| `pyfory.tagged_uint64` | tagged | 1-9 字节 | +| `pyfory.float32` | fixed | 4 字节 | +| `pyfory.float64` | fixed | 8 字节 | -**When to Use**: +**何时使用:** -- `varint`: Best for values that are often small (default for int32/int64/uint32/uint64) -- `fixed`: Best for values that use full range (e.g., timestamps, hashes) -- `tagged`: When type information needs to be preserved (uint64 only) +- `varint`:适合小值占多数的场景(int32/int64/uint32/uint64 默认) +- `fixed`:适合覆盖全值域的场景(例如时间戳、哈希) +- `tagged`:适合需要保留类型信息的场景(仅 uint64) -## Complete Example +## 完整示例 ```python from dataclasses import dataclass @@ -361,9 +358,9 @@ if __name__ == "__main__": main() ``` -## Cross-Language Compatibility +## 跨语言兼容 -When serializing data to be read by other languages (Java, Rust, C++, Go), use field IDs and matching type annotations: +当序列化数据将被其他语言(Java、Rust、C++、Go)读取时,建议使用字段 ID 并配套类型注解: ```python @dataclass @@ -375,9 +372,9 @@ class CrossLangData: optional_value: Optional[str] = pyfory.field(id=3, nullable=True, default=None) ``` -## Schema Evolution +## Schema 演进 -Compatible mode supports schema evolution. It is recommended to configure field IDs to reduce serialization cost: +兼容模式支持 Schema 演进。建议通过字段 ID 降低序列化成本: ```python # Version 1 @@ -395,9 +392,9 @@ class DataV2: email: Optional[str] = pyfory.field(id=2, nullable=True, default=None) # New field ``` -Data serialized with V1 can be deserialized with V2 (new field will be `None`). +V1 写出的数据可由 V2 读取(新增字段将为 `None`)。 -Alternatively, field IDs can be omitted (field names will be used in metadata with larger overhead): +也可以不配置字段 ID(此时元信息使用字段名,开销更大): ```python @dataclass @@ -406,21 +403,21 @@ class Data: name: str = "" ``` -## Native Mode vs Xlang Mode +## Native 模式与 Xlang 模式 -Field configuration behaves differently depending on the serialization mode: +字段配置会随序列化模式不同而变化。 -### Native Mode (Python-only) +### Native 模式(仅 Python) -Native mode has **relaxed default values** for maximum compatibility: +Native 模式默认值更宽松,以获得更高兼容性: -- **Nullable**: `str` and numeric types are non-nullable by default unless `Optional` is used -- **Ref tracking**: Enabled by default for object references (except `str` and numeric types) +- **Nullable**:`str` 和数值类型默认不可空,除非使用 `Optional` +- **Ref tracking**:对象引用默认开启(`str` 与数值类型除外) -In native mode, you typically **don't need to configure field annotations** unless you want to: +在 Native 模式中,通常**不需要显式字段配置**,除非你希望: -- Reduce serialized size by using field IDs -- Optimize performance by disabling unnecessary ref tracking +- 通过字段 ID 降低序列化体积 +- 关闭不必要的 ref 跟踪以优化性能 ```python # Native mode: works without field configuration @@ -431,19 +428,19 @@ class User: tags: List[str] = None ``` -### Xlang Mode (Cross-language) +### Xlang 模式(跨语言) -Xlang mode has **stricter default values** due to type system differences between languages: +由于语言间类型系统差异,Xlang 模式默认值更严格: -- **Nullable**: Fields are non-nullable by default (`nullable=False`) -- **Ref tracking**: Disabled by default (`ref=False`) +- **Nullable**:默认不可空(`nullable=False`) +- **Ref tracking**:默认关闭(`ref=False`) -In xlang mode, you **need to configure fields** when: +在 Xlang 模式中,以下情况需要显式配置: -- A field can be None (use `Optional[T]` with `nullable=True`) -- A field needs reference tracking for shared/circular objects (use `ref=True`) -- Integer types need specific encoding for cross-language compatibility -- You want to reduce metadata size (use field IDs) +- 字段可能为 None(`Optional[T]` + `nullable=True`) +- 字段需要共享/循环引用语义(`ref=True`) +- 整数类型需要指定跨语言编码 +- 需要减少元信息开销(字段 ID) ```python # Xlang mode: explicit configuration required for nullable/ref fields @@ -455,41 +452,41 @@ class User: friend: Optional["User"] = pyfory.field(id=3, ref=True, nullable=True, default=None) # Must declare ref ``` -### Default Values Summary - -| Option | Native Mode Default | Xlang Mode Default | -| ---------- | ----------------------------------------------------- | ------------------ | -| `nullable` | `False` for `str`/numeric; others nullable by default | `False` | -| `ref` | `True` (except `str` and numeric types) | `False` | -| `dynamic` | `True` (except numeric/str/time types) | `False` (concrete) | - -## Best Practices - -1. **Configure field IDs**: Recommended for compatible mode to reduce serialization cost -2. **Use `Optional[T]` with `nullable=True`**: Required for nullable fields in xlang mode -3. **Enable ref tracking for shared objects**: Use `ref=True` when objects are shared or circular -4. **Use `ignore=True` for sensitive data**: Passwords, tokens, internal state -5. **Choose appropriate encoding**: `varint` for small values, `fixed` for full-range values -6. **Keep IDs stable**: Once assigned, don't change field IDs - -## Options Reference - -| Configuration | Description | -| -------------------------------------------- | ------------------------------------ | -| `pyfory.field(id=N)` | Field tag ID to reduce metadata size | -| `pyfory.field(nullable=True)` | Mark field as nullable | -| `pyfory.field(ref=True)` | Enable reference tracking | -| `pyfory.field(ignore=True)` | Exclude field from serialization | -| `pyfory.field(dynamic=True)` | Force type info to be written | -| `pyfory.field(dynamic=False)` | Skip type info (use declared type) | -| `Optional[T]` | Type hint for nullable fields | -| `pyfory.int32`, `pyfory.int64` | Signed integers (varint encoding) | -| `pyfory.uint32`, `pyfory.uint64` | Unsigned integers (varint encoding) | -| `pyfory.fixed_uint32`, `pyfory.fixed_uint64` | Fixed-size unsigned | -| `pyfory.tagged_uint64` | Tagged encoding for uint64 | - -## Related Topics - -- [Basic Serialization](basic_serialization) - Getting started with Fory serialization -- [Schema Evolution](schema_evolution) - Compatible mode and schema evolution -- [Cross-Language](cross_language) - Interoperability with Java, Rust, C++, Go +### 默认值汇总 + +| 选项 | Native 模式默认值 | Xlang 模式默认值 | +| ---------- | ------------------------------------------ | ------------------- | +| `nullable` | `str`/数值类型为 `False`,其余对象通常可空 | `False` | +| `ref` | `True`(`str` 和数值类型除外) | `False` | +| `dynamic` | `True`(数值/str/time 类型除外) | `False`(具体类型) | + +## 最佳实践 + +1. **配置字段 ID**:兼容模式下建议配置,降低序列化成本 +2. **`Optional[T]` 配合 `nullable=True`**:xlang 下可空字段需要显式声明 +3. **共享对象启用 ref**:共享或循环关系使用 `ref=True` +4. **敏感字段使用 `ignore=True`**:例如密码、令牌、内部状态 +5. **选择合适编码**:小值用 `varint`,全范围值用 `fixed` +6. **保持 ID 稳定**:分配后不要更改字段 ID + +## 选项速查 + +| 配置 | 说明 | +| -------------------------------------------- | ------------------------------ | +| `pyfory.field(id=N)` | 字段 tag ID,减少元信息开销 | +| `pyfory.field(nullable=True)` | 标记字段可空 | +| `pyfory.field(ref=True)` | 启用引用跟踪 | +| `pyfory.field(ignore=True)` | 将字段排除在序列化之外 | +| `pyfory.field(dynamic=True)` | 强制写入类型信息 | +| `pyfory.field(dynamic=False)` | 跳过类型信息(按声明类型处理) | +| `Optional[T]` | 可空字段类型提示 | +| `pyfory.int32`, `pyfory.int64` | 有符号整数(varint 编码) | +| `pyfory.uint32`, `pyfory.uint64` | 无符号整数(varint 编码) | +| `pyfory.fixed_uint32`, `pyfory.fixed_uint64` | 定长无符号整数 | +| `pyfory.tagged_uint64` | uint64 的 tagged 编码 | + +## 相关主题 + +- [基础序列化](basic_serialization) - 快速上手 Fory 序列化 +- [Schema 演进](schema_evolution) - 兼容模式与 schema 演进 +- [跨语言](cross_language) - 与 Java、Rust、C++、Go 互操作 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.13/introduction/overview.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.13/introduction/overview.md index 7a5a2a685c..28831ecb10 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.13/introduction/overview.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.13/introduction/overview.md @@ -55,12 +55,12 @@ Apache Fory™ 通过先进的优化技术提供卓越性能: Apache Fory™ 实现了针对不同场景优化的多个二进制协议: -| 协议 | 使用场景 | 核心特性 | -| ------------------------------------------------------------------------- | ---------------------- | -------------------------------------------- | -| **[跨语言序列化](../specification/xlang_serialization_spec.md)** | 跨语言对象交换 | 自动序列化、引用、多态 | -| **[Java 序列化](../specification/java_serialization_spec.md)** | 高性能 Java 专用 | JDK 序列化的直接替代,快 100 倍 | -| **[行格式](../specification/row_format_spec.md)** | 分析和数据处理 | 零拷贝随机访问、Arrow 兼容 | -| **Python 原生** | Python 专用序列化 | Pickle/cloudpickle 替代,性能更好 | +| 协议 | 使用场景 | 核心特性 | +| ---------------------------------------------------------------- | ----------------- | --------------------------------- | +| **[跨语言序列化](../specification/xlang_serialization_spec.md)** | 跨语言对象交换 | 自动序列化、引用、多态 | +| **[Java 序列化](../specification/java_serialization_spec.md)** | 高性能 Java 专用 | JDK 序列化的直接替代,快 100 倍 | +| **[行格式](../specification/row_format_spec.md)** | 分析和数据处理 | 零拷贝随机访问、Arrow 兼容 | +| **Python 原生** | Python 专用序列化 | Pickle/cloudpickle 替代,性能更好 | 所有协议共享相同的优化代码库,一个协议的改进可以惠及其他协议。 @@ -68,25 +68,25 @@ Apache Fory™ 实现了针对不同场景优化的多个二进制协议: ### 用户指南 -| 指南 | 描述 | 源文件 | 网站 | -| ---------------------- | --------------------------------- | --------------------------------------------------------------- | ----------------------------------------------------------------------------------- | -| **Java 序列化** | Java 序列化综合指南 | [java_serialization_guide.md](../guide/java_serialization_guide.md) | [📖 查看](https://fory.apache.org/docs/guide/java_serialization) | -| **跨语言序列化** | 多语言对象交换 | [xlang_serialization_guide.md](../guide/xlang_serialization_guide.md) | [📖 查看](https://fory.apache.org/docs/specification/fory_xlang_serialization_spec) | -| **行格式** | 零拷贝随机访问格式 | [row_format_guide.md](../guide/row_format_guide.md) | [📖 查看](https://fory.apache.org/docs/specification/fory_row_format_spec) | -| **Python** | Python 特定功能和用法 | [python_guide.md](../guide/python_guide.md) | [📖 查看](https://fory.apache.org/docs/guide/python_serialization) | -| **Rust** | Rust 实现和模式 | [rust_guide.md](../guide/rust_guide.md) | [📖 查看](https://fory.apache.org/docs/guide/rust_serialization) | -| **Scala** | Scala 集成和最佳实践 | [scala_guide.md](../guide/scala_guide.md) | [📖 查看](https://fory.apache.org/docs/guide/scala_serialization) | -| **GraalVM** | 原生镜像支持和 AOT 编译 | [graalvm_guide.md](../guide/graalvm_guide.md) | [📖 查看](https://fory.apache.org/docs/guide/graalvm_serialization) | -| **开发** | 构建和贡献 Fory | [DEVELOPMENT.md](../guide/DEVELOPMENT.md) | [📖 查看](https://fory.apache.org/docs/guide/development) | +| 指南 | 描述 | 源文件 | 网站 | +| ---------------- | ----------------------- | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| **Java 序列化** | Java 序列化综合指南 | [java_serialization_guide.md](../guide/java_serialization_guide.md) | [📖 查看](https://fory.apache.org/docs/guide/java_serialization) | +| **跨语言序列化** | 多语言对象交换 | [xlang_serialization_guide.md](../guide/xlang_serialization_guide.md) | [📖 查看](https://fory.apache.org/docs/specification/fory_xlang_serialization_spec) | +| **行格式** | 零拷贝随机访问格式 | [row_format_guide.md](../guide/row_format_guide.md) | [📖 查看](https://fory.apache.org/docs/specification/fory_row_format_spec) | +| **Python** | Python 特定功能和用法 | [python_guide.md](../guide/python_guide.md) | [📖 查看](https://fory.apache.org/docs/guide/python_serialization) | +| **Rust** | Rust 实现和模式 | [rust_guide.md](../guide/rust_guide.md) | [📖 查看](https://fory.apache.org/docs/guide/rust_serialization) | +| **Scala** | Scala 集成和最佳实践 | [scala_guide.md](../guide/scala_guide.md) | [📖 查看](https://fory.apache.org/docs/guide/scala_serialization) | +| **GraalVM** | 原生镜像支持和 AOT 编译 | [graalvm_guide.md](../guide/graalvm_guide.md) | [📖 查看](https://fory.apache.org/docs/guide/graalvm_serialization) | +| **开发** | 构建和贡献 Fory | [DEVELOPMENT.md](../guide/DEVELOPMENT.md) | [📖 查看](https://fory.apache.org/docs/guide/development) | ### 协议规范 -| 规范 | 描述 | 源文件 | 网站 | -| ---------------------- | ------------------------ | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | -| **跨语言序列化** | 跨语言二进制协议 | [xlang_serialization_spec.md](../specification/xlang_serialization_spec.md) | [📖 查看](https://fory.apache.org/docs/specification/fory_xlang_serialization_spec) | -| **Java 序列化** | Java 优化协议 | [java_serialization_spec.md](../specification/java_serialization_spec.md) | [📖 查看](https://fory.apache.org/docs/specification/fory_java_serialization_spec) | -| **行格式** | 基于行的二进制格式 | [row_format_spec.md](../specification/row_format_spec.md) | [📖 查看](https://fory.apache.org/docs/specification/fory_row_format_spec) | -| **类型映射** | 跨语言类型转换 | [xlang_type_mapping.md](../specification/xlang_type_mapping.md) | [📖 查看](https://fory.apache.org/docs/specification/fory_xlang_serialization_spec) | +| 规范 | 描述 | 源文件 | 网站 | +| ---------------- | ------------------ | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| **跨语言序列化** | 跨语言二进制协议 | [xlang_serialization_spec.md](../specification/xlang_serialization_spec.md) | [📖 查看](https://fory.apache.org/docs/specification/fory_xlang_serialization_spec) | +| **Java 序列化** | Java 优化协议 | [java_serialization_spec.md](../specification/java_serialization_spec.md) | [📖 查看](https://fory.apache.org/docs/specification/fory_java_serialization_spec) | +| **行格式** | 基于行的二进制格式 | [row_format_spec.md](../specification/row_format_spec.md) | [📖 查看](https://fory.apache.org/docs/specification/fory_row_format_spec) | +| **类型映射** | 跨语言类型转换 | [xlang_type_mapping.md](../specification/xlang_type_mapping.md) | [📖 查看](https://fory.apache.org/docs/specification/fory_xlang_serialization_spec) | ## 兼容性 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.14/guide/cpp/schema-evolution.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.14/guide/cpp/schema-evolution.md index 3f89d97aad..fd8c7bfcad 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.14/guide/cpp/schema-evolution.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.14/guide/cpp/schema-evolution.md @@ -85,7 +85,7 @@ Compatible 模式支持以下 schema 变更: | 添加新字段 | ✅ | 缺失字段使用默认值 | | 删除字段 | ✅ | 额外字段被跳过 | | 重排字段顺序 | ✅ | 按名称匹配字段,而非位置 | -| 更改可空性 | ✅ | `T` ↔ `std::optional` | +| 更改可空性 | ✅ | `T` ↔ `std::optional` | | 更改字段类型 | ❌ | 类型必须兼容 | | 重命名字段 | ❌ | 字段名必须匹配(区分大小写) | diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15.json b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15.json new file mode 100644 index 0000000000..5134c6519e --- /dev/null +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15.json @@ -0,0 +1,22 @@ +{ + "version.label": { + "message": "0.15", + "description": "The label for version 0.15" + }, + "sidebar.docsSidebar.category.Introduction": { + "message": "Apache Fory 介绍", + "description": "The label for category Introduction in sidebar docsSidebar" + }, + "sidebar.docsSidebar.category.Start": { + "message": "快速开始", + "description": "The label for category Start in sidebar docsSidebar" + }, + "sidebar.docsSidebar.category.Schema IDL & Compiler": { + "message": "Schema IDL 与编译器", + "description": "The label for category Schema IDL & Compiler in sidebar docsSidebar" + }, + "sidebar.docsSidebar.category.Guide": { + "message": "用户指南", + "description": "The label for category Guide in sidebar docsSidebar" + } +} diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/benchmarks/go/benchmark_report.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/benchmarks/go/benchmark_report.md index a1c3d635f2..f73aacf0a2 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/benchmarks/go/benchmark_report.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/benchmarks/go/benchmark_report.md @@ -10,48 +10,48 @@ ## 性能摘要 -| 数据类型 | 操作 | Fory (ops/s) | Protobuf (ops/s) | Msgpack (ops/s) | Fory vs PB | Fory vs MP | -|---------|------|--------------|------------------|-----------------|------------|------------| -| Struct | 序列化 | 15.16M | 10.23M | 5.41M | 1.48x | 2.80x | -| Struct | 反序列化 | 12.10M | 11.01M | 3.23M | 1.10x | 3.75x | -| Structlist | 序列化 | 1.58M | 561K | 299K | 2.82x | 5.28x | -| Structlist | 反序列化 | 1.10M | 529K | 175K | 2.09x | 6.30x | -| Sample | 序列化 | 7.28M | 2.72M | 670K | 2.68x | 10.87x | -| Sample | 反序列化 | 3.79M | 2.37M | 376K | 1.60x | 10.09x | -| Samplelist | 序列化 | 510K | 141K | 38K | 3.61x | 13.34x | -| Samplelist | 反序列化 | 236K | 107K | 19K | 2.20x | 12.66x | -| Mediacontent | 序列化 | 3.72M | 2.12M | 1.29M | 1.75x | 2.88x | -| Mediacontent | 反序列化 | 2.34M | 1.81M | 698K | 1.30x | 3.35x | -| Mediacontentlist | 序列化 | 268K | 110K | 72K | 2.44x | 3.72x | -| Mediacontentlist | 反序列化 | 138K | 87K | 36K | 1.58x | 3.86x | +| 数据类型 | 操作 | Fory (ops/s) | Protobuf (ops/s) | Msgpack (ops/s) | Fory vs PB | Fory vs MP | +| ---------------- | -------- | ------------ | ---------------- | --------------- | ---------- | ---------- | +| Struct | 序列化 | 15.16M | 10.23M | 5.41M | 1.48x | 2.80x | +| Struct | 反序列化 | 12.10M | 11.01M | 3.23M | 1.10x | 3.75x | +| Structlist | 序列化 | 1.58M | 561K | 299K | 2.82x | 5.28x | +| Structlist | 反序列化 | 1.10M | 529K | 175K | 2.09x | 6.30x | +| Sample | 序列化 | 7.28M | 2.72M | 670K | 2.68x | 10.87x | +| Sample | 反序列化 | 3.79M | 2.37M | 376K | 1.60x | 10.09x | +| Samplelist | 序列化 | 510K | 141K | 38K | 3.61x | 13.34x | +| Samplelist | 反序列化 | 236K | 107K | 19K | 2.20x | 12.66x | +| Mediacontent | 序列化 | 3.72M | 2.12M | 1.29M | 1.75x | 2.88x | +| Mediacontent | 反序列化 | 2.34M | 1.81M | 698K | 1.30x | 3.35x | +| Mediacontentlist | 序列化 | 268K | 110K | 72K | 2.44x | 3.72x | +| Mediacontentlist | 反序列化 | 138K | 87K | 36K | 1.58x | 3.86x | ## 详细耗时(ns/op) -| 数据类型 | 操作 | Fory | Protobuf | Msgpack | -|---------|------|------|----------|---------| -| Struct | 序列化 | 66.0 | 97.8 | 184.9 | -| Struct | 反序列化 | 82.7 | 90.9 | 309.6 | -| Structlist | 序列化 | 632.8 | 1783.0 | 3340.0 | -| Structlist | 反序列化 | 906.4 | 1891.0 | 5709.0 | -| Sample | 序列化 | 137.3 | 367.3 | 1492.0 | -| Sample | 反序列化 | 263.6 | 422.2 | 2661.0 | -| Samplelist | 序列化 | 1962.0 | 7087.0 | 26169.0 | -| Samplelist | 反序列化 | 4234.0 | 9321.0 | 53615.0 | -| Mediacontent | 序列化 | 268.8 | 471.1 | 773.7 | -| Mediacontent | 反序列化 | 426.9 | 553.1 | 1432.0 | -| Mediacontentlist | 序列化 | 3736.0 | 9107.0 | 13911.0 | -| Mediacontentlist | 反序列化 | 7247.0 | 11435.0 | 27975.0 | +| 数据类型 | 操作 | Fory | Protobuf | Msgpack | +| ---------------- | -------- | ------ | -------- | ------- | +| Struct | 序列化 | 66.0 | 97.8 | 184.9 | +| Struct | 反序列化 | 82.7 | 90.9 | 309.6 | +| Structlist | 序列化 | 632.8 | 1783.0 | 3340.0 | +| Structlist | 反序列化 | 906.4 | 1891.0 | 5709.0 | +| Sample | 序列化 | 137.3 | 367.3 | 1492.0 | +| Sample | 反序列化 | 263.6 | 422.2 | 2661.0 | +| Samplelist | 序列化 | 1962.0 | 7087.0 | 26169.0 | +| Samplelist | 反序列化 | 4234.0 | 9321.0 | 53615.0 | +| Mediacontent | 序列化 | 268.8 | 471.1 | 773.7 | +| Mediacontent | 反序列化 | 426.9 | 553.1 | 1432.0 | +| Mediacontentlist | 序列化 | 3736.0 | 9107.0 | 13911.0 | +| Mediacontentlist | 反序列化 | 7247.0 | 11435.0 | 27975.0 | ### 序列化后数据大小(字节) -| 数据类型 | Fory | Protobuf | Msgpack | -|---------|------|----------|---------| -| Struct | 58 | 61 | 57 | -| Sample | 446 | 375 | 524 | -| MediaContent | 342 | 301 | 400 | -| StructList | 560 | 1260 | 1146 | -| SampleList | 7600 | 7560 | 10486 | -| MediaContentList | 5776 | 6080 | 8006 | +| 数据类型 | Fory | Protobuf | Msgpack | +| ---------------- | ---- | -------- | ------- | +| Struct | 58 | 61 | 57 | +| Sample | 446 | 375 | 524 | +| MediaContent | 342 | 301 | 400 | +| StructList | 560 | 1260 | 1146 | +| SampleList | 7600 | 7560 | 10486 | +| MediaContentList | 5776 | 6080 | 8006 | ## 性能图表 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/_category_.json b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/_category_.json new file mode 100644 index 0000000000..abf19e9fcb --- /dev/null +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 3, + "label": "Schema IDL 与编译器", + "collapsible": true, + "collapsed": true +} diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/compiler-guide.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/compiler-guide.md index 1c8184bfda..0046cbcd3b 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/compiler-guide.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/compiler-guide.md @@ -19,9 +19,7 @@ license: | limitations under the License. --- -> 中文导读:本文档为 Fory 编译器/协议规范文档的中文译稿。为避免改变规范语义,代码片段、类型名、协议字段名保持英文,说明性文字优先翻译为中文。 - -本指南介绍 Fory IDL 编译器的安装、使用与集成。 +本指南介绍 Fory IDL 编译器的安装、命令行使用方式以及构建系统集成方案。 ## 安装 @@ -52,155 +50,153 @@ foryc --scan-generated [OPTIONS] ### 选项 -Compile options: - -| Option | Description | Default | -| ------------------------------------- | ----------------------------------------------------- | ------------------- | -| `--lang` | Comma-separated target languages | `all` | -| `--output`, `-o` | Output directory | `./generated` | -| `--package` | Override package name from Fory IDL file | (from file) | -| `-I`, `--proto_path`, `--import_path` | Add directory to import search path (can be repeated) | (none) | -| `--java_out=DST_DIR` | Generate Java code in DST_DIR | (none) | -| `--python_out=DST_DIR` | Generate Python code in DST_DIR | (none) | -| `--cpp_out=DST_DIR` | Generate C++ code in DST_DIR | (none) | -| `--go_out=DST_DIR` | Generate Go code in DST_DIR | (none) | -| `--rust_out=DST_DIR` | Generate Rust code in DST_DIR | (none) | -| `--go_nested_type_style` | Go nested type naming: `camelcase` or `underscore` | from schema/default | -| `--emit-fdl` | Print translated Fory IDL for non-`.fdl` inputs | `false` | -| `--emit-fdl-path` | Write translated Fory IDL to a file or directory | (stdout) | - -Scan options (with `--scan-generated`): - -| Option | Description | Default | -| ------------ | ------------------------------ | ------- | -| `--root` | Root directory to scan | `.` | -| `--relative` | Print paths relative to root | `false` | -| `--delete` | Delete matched generated files | `false` | -| `--dry-run` | Scan/print only, do not delete | `false` | - -### Scan Generated Files - -Use `--scan-generated` to find files produced by `foryc`. The scanner walks -the tree recursively, skips `build/`, `target/`, and hidden directories, and prints -each generated file as it is found. +编译选项: + +| 选项 | 说明 | 默认值 | +| ------------------------------------- | ------------------------------------------------ | ------------- | +| `--lang` | 目标语言列表(逗号分隔) | `all` | +| `--output`, `-o` | 输出目录 | `./generated` | +| `--package` | 覆盖 Fory IDL 文件中的 package | (来自文件) | +| `-I`, `--proto_path`, `--import_path` | 添加 import 搜索路径(可重复) | (无) | +| `--java_out=DST_DIR` | 将 Java 代码输出到 `DST_DIR` | (无) | +| `--python_out=DST_DIR` | 将 Python 代码输出到 `DST_DIR` | (无) | +| `--cpp_out=DST_DIR` | 将 C++ 代码输出到 `DST_DIR` | (无) | +| `--go_out=DST_DIR` | 将 Go 代码输出到 `DST_DIR` | (无) | +| `--rust_out=DST_DIR` | 将 Rust 代码输出到 `DST_DIR` | (无) | +| `--go_nested_type_style` | Go 嵌套类型命名风格:`camelcase` 或 `underscore` | schema/默认值 | +| `--emit-fdl` | 对非 `.fdl` 输入打印转换后的 Fory IDL | `false` | +| `--emit-fdl-path` | 将转换后的 Fory IDL 写入文件或目录 | (stdout) | + +扫描选项(配合 `--scan-generated`): + +| 选项 | 说明 | 默认值 | +| ------------ | ---------------------- | ------- | +| `--root` | 扫描根目录 | `.` | +| `--relative` | 以相对路径输出 | `false` | +| `--delete` | 删除匹配到的生成文件 | `false` | +| `--dry-run` | 仅扫描输出,不执行删除 | `false` | + +### 扫描生成文件 + +使用 `--scan-generated` 可以定位 `foryc` 生成的文件。扫描器会递归遍历目录树,跳过 `build/`、`target/` 和隐藏目录,并输出找到的每个生成文件。 ```bash -# Scan current directory +# 扫描当前目录 foryc --scan-generated -# Scan a specific root +# 扫描指定根目录 foryc --scan-generated --root ./src -# Print paths relative to the scan root +# 输出相对路径 foryc --scan-generated --root ./src --relative -# Delete scanned generated files +# 删除扫描到的生成文件 foryc --scan-generated --root ./src --delete -# Dry-run (scan and print only) +# Dry-run(仅扫描与输出) foryc --scan-generated --root ./src --dry-run ``` -### Examples +### 示例 -**Compile for all languages:** +**为所有语言编译:** ```bash foryc schema.fdl ``` -**Compile for specific languages:** +**为指定语言编译:** ```bash foryc schema.fdl --lang java,python ``` -**Specify output directory:** +**指定输出目录:** ```bash foryc schema.fdl --output ./src/generated ``` -**Override package name:** +**覆盖 package:** ```bash foryc schema.fdl --package com.myapp.models ``` -**Compile multiple files:** +**编译多个文件:** ```bash foryc user.fdl order.fdl product.fdl --output ./generated ``` -**Use import search paths:** +**使用 import 搜索路径:** ```bash -# Add a single import path +# 单个路径 foryc src/main.fdl -I libs/common -# Add multiple import paths (repeated option) +# 多个路径(重复参数) foryc src/main.fdl -I libs/common -I libs/types -# Add multiple import paths (comma-separated) +# 多个路径(逗号分隔) foryc src/main.fdl -I libs/common,libs/types,third_party/ -# Using --proto_path (protoc-compatible alias) +# --proto_path(protoc 兼容别名) foryc src/main.fdl --proto_path=libs/common -# Mix all styles +# 混合写法 foryc src/main.fdl -I libs/common,libs/types --proto_path third_party/ ``` -**Language-specific output directories (protoc-style):** +**语言定向输出目录(protoc 风格):** ```bash -# Generate only Java code to a specific directory +# 仅生成 Java foryc schema.fdl --java_out=./src/main/java -# Generate multiple languages to different directories +# 多语言分别输出到不同目录 foryc schema.fdl --java_out=./java/gen --python_out=./python/src --go_out=./go/gen -# Combine with import paths +# 结合 import 路径 foryc schema.fdl --java_out=./gen/java -I proto/ -I common/ ``` -When using `--{lang}_out` options: +使用 `--{lang}_out` 时: -- Only the specified languages are generated (not all languages) -- The compiler writes under the specified directory (language-specific generators may still create package/module subdirectories) -- This is compatible with protoc-style workflows +- 只生成显式指定的语言(不会生成全部语言) +- 输出写入指定目录(语言生成器可能继续按包/模块分层) +- 兼容 protoc 风格工作流 -**Inspect translated Fory IDL from proto/fbs input:** +**查看 proto/fbs 输入转换后的 Fory IDL:** ```bash -# Print translated Fory IDL to stdout +# 输出到 stdout foryc schema.proto --emit-fdl -# Write translated Fory IDL to a directory +# 输出到目录 foryc schema.fbs --emit-fdl --emit-fdl-path ./translated ``` -## Import Path Resolution +## Import 路径解析 -When compiling Fory IDL files with imports, the compiler searches for imported files in this order: +编译含 import 的 Fory IDL 文件时,导入文件按以下顺序查找: -1. **Relative to the importing file (default)** - The directory containing the file with the import statement is always searched first, automatically. No `-I` flag needed for same-directory imports. -2. **Each `-I` path in order** - Additional search paths specified on the command line +1. **相对于导入者文件目录(默认)**:始终优先查找,无需 `-I` +2. **按顺序遍历每个 `-I` 路径** -**Same-directory imports work automatically:** +**同目录 import 可直接生效:** ```protobuf // main.fdl -import "common.fdl"; // Found if common.fdl is in the same directory +import "common.fdl"; // 若 common.fdl 在同目录,将自动找到 ``` ```bash -# No -I needed for same-directory imports +# 同目录导入无需 -I foryc main.fdl ``` -**Example project structure:** +**示例目录结构:** ``` project/ @@ -210,7 +206,7 @@ project/ └── common.fdl ``` -**Without `-I` (fails):** +**不加 `-I`(失败):** ```bash $ foryc src/main.fdl @@ -218,7 +214,7 @@ Import error: Import not found: common.fdl Searched in: /project/src ``` -**With `-I` (succeeds):** +**加 `-I`(成功):** ```bash $ foryc src/main.fdl -I libs/ @@ -226,17 +222,17 @@ Compiling src/main.fdl... Resolved 1 import(s) ``` -## Supported Languages +## 支持语言 -| Language | Flag | Output Extension | Description | -| -------- | -------- | ---------------- | --------------------------- | -| Java | `java` | `.java` | POJOs with Fory annotations | -| Python | `python` | `.py` | Dataclasses with type hints | -| Go | `go` | `.go` | Structs with struct tags | -| Rust | `rust` | `.rs` | Structs with derive macros | -| C++ | `cpp` | `.h` | Structs with FORY macros | +| 语言 | 标记 | 输出后缀 | 说明 | +| ------ | -------- | -------- | ---------------------- | +| Java | `java` | `.java` | 带 Fory 注解的 POJO | +| Python | `python` | `.py` | 带类型提示的 dataclass | +| Go | `go` | `.go` | 带 struct tag 的结构体 | +| Rust | `rust` | `.rs` | 带 derive 宏的结构体 | +| C++ | `cpp` | `.h` | 带 FORY 宏的结构体 | -## Output Structure +## 输出结构 ### Java @@ -251,9 +247,9 @@ generated/ └── ExampleForyRegistration.java ``` -- One file per type (enum or message) -- Package structure matches Fory IDL package -- Registration helper class generated +- 每个类型(enum/message)单独一个文件 +- 包路径与 Fory IDL package 一致 +- 会生成注册辅助类 ### Python @@ -263,9 +259,9 @@ generated/ └── example.py ``` -- Single module with all types -- Module name derived from package -- Registration function included +- 所有类型位于单模块 +- 模块名由 package 派生 +- 包含注册函数 ### Go @@ -276,9 +272,9 @@ generated/ └── example.go ``` -- Single file with all types -- Directory and package name are derived from `go_package` or the Fory IDL package -- Registration function included +- 所有类型在单文件中 +- 目录名与包名来自 `go_package` 或 Fory IDL package +- 包含注册函数 ### Rust @@ -288,9 +284,9 @@ generated/ └── example.rs ``` -- Single module with all types -- Module name derived from package -- Registration function included +- 所有类型位于单模块 +- 模块名由 package 派生 +- 包含注册函数 ### C++ @@ -300,15 +296,15 @@ generated/ └── example.h ``` -- Single header file -- Namespace matches package (dots to `::`) -- Header guards and forward declarations +- 单头文件输出 +- 命名空间与 package 对齐(点号转换为 `::`) +- 自动包含 header guard 与前向声明 -## Build Integration +## 构建系统集成 ### Maven (Java) -Add to your `pom.xml`: +在 `pom.xml` 中添加: ```xml @@ -339,7 +335,7 @@ Add to your `pom.xml`: ``` -Add generated sources: +添加生成源码目录: ```xml @@ -368,7 +364,7 @@ Add generated sources: ### Gradle (Java/Kotlin) -Add to `build.gradle`: +在 `build.gradle` 中添加: ```groovy task generateForyTypes(type: Exec) { @@ -390,7 +386,7 @@ sourceSets { ### Python (setuptools) -Add to `setup.py` or `pyproject.toml`: +在 `setup.py` 或 `pyproject.toml` 中加入生成步骤: ```python # setup.py @@ -413,24 +409,24 @@ setup( ) ``` -### Go (go generate) +### Go (`go generate`) -Add to your Go file: +在 Go 文件中添加: ```go //go:generate foryc ../schema.fdl --lang go --output . package models ``` -Run: +执行: ```bash go generate ./... ``` -### Rust (build.rs) +### Rust (`build.rs`) -Add to `build.rs`: +在 `build.rs` 中添加: ```rust use std::process::Command; @@ -451,7 +447,7 @@ fn main() { ### CMake (C++) -Add to `CMakeLists.txt`: +在 `CMakeLists.txt` 中添加: ```cmake find_program(FORY_COMPILER foryc) @@ -474,7 +470,7 @@ target_include_directories(mylib PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/generated) ### Bazel -Create a rule in `BUILD`: +在 `BUILD` 中添加规则: ```python genrule( @@ -492,51 +488,51 @@ cc_library( ) ``` -## Error Handling +## 错误处理 -### Syntax Errors +### 语法错误 ``` Error: Line 5, Column 12: Expected ';' after field declaration ``` -Fix: Check the indicated line for missing semicolons or syntax issues. +修复方式:检查对应行是否缺少分号或存在语法问题。 -### Duplicate Type Names +### 类型名重复 ``` Error: Duplicate type name: User ``` -Fix: Ensure each enum and message has a unique name within the file. +修复方式:确保同一文件内每个 enum/message 名称唯一。 -### Duplicate Type IDs +### 类型 ID 重复 ``` Error: Duplicate type ID 100: User and Order ``` -Fix: Assign unique type IDs to each type. +修复方式:为每个类型分配唯一 ID。 -### Unknown Type References +### 未知类型引用 ``` Error: Unknown type 'Address' in Customer.address ``` -Fix: Define the referenced type before using it, or check for typos. +修复方式:先定义被引用类型,或检查类型名拼写。 -### Duplicate Field Numbers +### 字段号重复 ``` Error: Duplicate field number 1 in User: name and id ``` -Fix: Assign unique field numbers within each message. +修复方式:确保同一 message 内字段号唯一。 -## Best Practices +## 最佳实践 -### Project Structure +### 项目结构 ``` project/ @@ -549,12 +545,12 @@ project/ └── build.gradle ``` -### Version Control +### 版本控制 -- **Track**: Fory IDL schema files -- **Ignore**: Generated code (can be regenerated) +- **纳入版本控制**:Fory IDL schema 文件 +- **忽略生成代码**:可在构建时再生成 -Add to `.gitignore`: +在 `.gitignore` 中加入: ``` # Generated Fory IDL code @@ -562,12 +558,12 @@ src/generated/ generated/ ``` -### CI/CD Integration +### CI/CD 集成 -Always regenerate during builds: +在构建流程中始终重新生成代码: ```yaml -# GitHub Actions example +# GitHub Actions 示例 steps: - name: Install Fory IDL Compiler run: pip install ./compiler @@ -579,14 +575,14 @@ steps: run: ./gradlew build ``` -### Schema Evolution +### Schema 演进 -When modifying schemas: +修改 schema 时建议遵循: -1. **Never reuse field numbers** - Mark as reserved instead -2. **Never change type IDs** - They're part of the binary format -3. **Add new fields** - Use new field numbers -4. **Use `optional`** - For backward compatibility +1. **不要复用字段号**:删除字段后应保留/预留 +2. **不要改动类型 ID**:类型 ID 属于二进制协议的一部分 +3. **新增字段使用新字段号** +4. **优先使用 `optional`**:保持向后兼容 ```protobuf message User [id=100] { @@ -597,7 +593,7 @@ message User [id=100] { } ``` -## Troubleshooting +## 故障排查 ### Command Not Found @@ -605,7 +601,7 @@ message User [id=100] { foryc: command not found ``` -**Solution:** Ensure the compiler is installed and in your PATH: +**解决:** 确认编译器已安装且在 PATH 中: ```bash pip install -e ./compiler @@ -619,15 +615,15 @@ export PATH=$PATH:~/.local/bin Permission denied: ./generated ``` -**Solution:** Ensure write permissions on the output directory: +**解决:** 确保输出目录具备写权限: ```bash chmod -R u+w ./generated ``` -### Import Errors in Generated Code +### 生成代码 import 错误 -**Java:** Ensure Fory dependency is in your project: +**Java:** 确保项目包含 Fory 依赖: ```xml @@ -637,23 +633,23 @@ chmod -R u+w ./generated ``` -**Python:** Ensure pyfory is installed: +**Python:** 确保安装 `pyfory`: ```bash pip install pyfory ``` -**Go:** Ensure fory module is available: +**Go:** 确保可获取 fory 模块: ```bash go get github.com/apache/fory/go/fory ``` -**Rust:** Ensure fory crate is in `Cargo.toml`: +**Rust:** 确保 `Cargo.toml` 中包含 fory crate: ```toml [dependencies] fory = "x.y.z" ``` -**C++:** Ensure Fory headers are in include path. +**C++:** 确保编译器 include 路径可找到 Fory 头文件。 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/flatbuffers-idl.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/flatbuffers-idl.md index 579ac6c3fc..6a2bfd2885 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/flatbuffers-idl.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/flatbuffers-idl.md @@ -19,59 +19,49 @@ license: | limitations under the License. --- -> 中文导读:本文档为 Fory 编译器/协议规范文档的中文译稿。为避免改变规范语义,代码片段、类型名、协议字段名保持英文,说明性文字优先翻译为中文。 - 本页说明 Apache Fory 如何读取 FlatBuffers schema(`.fbs`)并将其转换为 Fory IR 以生成代码。 ## 本页内容 -- When to use FlatBuffers input with Fory -- Exact FlatBuffers to Fory mapping behavior -- Supported Fory-specific attributes in `.fbs` -- Migration notes and generated-code differences +- 何时应在 Fory 中使用 FlatBuffers 输入 +- FlatBuffers 到 Fory 的精确映射行为 +- `.fbs` 中支持的 Fory 扩展属性 +- 迁移注意事项与生成代码差异 ## 为什么使用 Apache Fory -- Idiomatic generated code: Fory generates language-idiomatic classes/structs - that can be used directly as domain objects. -- Java performance: In Java object-serialization workloads, Fory is faster than - FlatBuffers in Fory benchmarks. -- Other languages: serialization performance is generally in a similar range. -- Deserialization in practice: FlatBuffers does not perform native-object deserialization and is - faster by default, but if your application needs native objects, it requires - conversion and that conversion step can dominate read cost. In those cases, - Fory deserialization is often faster end-to-end. -- Easier APIs: Fory uses direct native objects, so you do not need to - reverse-build tables or manually manage offsets. -- Better graph modeling: Shared and circular references are first-class features - in Fory. +- **生成代码更符合语言习惯**:Fory 会生成各语言常用风格的类/结构体,可直接作为领域对象使用。 +- **Java 性能更优**:在 Fory 的 Java 对象序列化基准中,Fory 通常快于 FlatBuffers。 +- **其他语言性能相近**:序列化性能通常处于同一量级。 +- **实际反序列化链路更高效**:FlatBuffers 默认并不做原生对象反序列化,因此看起来更快;但当业务需要原生对象时,还需额外转换,这一步往往成为主要开销。在这种场景下,Fory 端到端反序列化通常更快。 +- **API 更简单**:Fory 直接操作原生对象,无需反向构建 table 或手动管理 offset。 +- **对象图建模能力更强**:Fory 原生支持共享引用和循环引用。 ## 快速决策指南 -| Situation | Recommended Path | -| ------------------------------------------------------------------ | ---------------------- | -| You already have `.fbs` schemas and want Fory runtime/codegen | Use FlatBuffers input | -| You are starting new schema work and want full Fory syntax control | Use native Fory IDL | -| You need FlatBuffers wire compatibility at runtime | Keep FlatBuffers stack | -| You need Fory object-graph semantics (`ref`, weak refs, etc.) | Use Fory | +| 场景 | 建议路径 | +| ----------------------------------------------- | ----------------------- | +| 已有 `.fbs` schema,想接入 Fory 运行时/代码生成 | 使用 FlatBuffers 输入 | +| 新建 schema,希望完整使用 Fory 语法能力 | 使用原生 Fory IDL | +| 运行时必须保持 FlatBuffers 线格式兼容 | 继续使用 FlatBuffers 栈 | +| 需要 Fory 对象图语义(`ref`、弱引用等) | 使用 Fory | ## FlatBuffers 到 Fory 的映射 -### Schema-Level Rules +### Schema 级规则 -- `namespace` maps to Fory package namespace. -- `include` entries map to Fory imports. -- `table` is translated as `evolving=true`. -- `struct` is translated as `evolving=false`. -- `root_type` is parsed but ignored by Fory runtime/codegen. -- `file_identifier` and `file_extension` are parsed but not used by Fory codegen. +- `namespace` 映射为 Fory package 命名空间。 +- `include` 映射为 Fory import。 +- `table` 会被翻译为 `evolving=true`。 +- `struct` 会被翻译为 `evolving=false`。 +- `root_type` 会被解析,但 Fory 运行时/代码生成不会使用。 +- `file_identifier` 与 `file_extension` 会被解析,但 Fory 代码生成不会使用。 -### Field Numbering +### 字段编号 -FlatBuffers fields do not have explicit field IDs. Fory assigns field numbers by -source declaration order, starting at `1`. +FlatBuffers 字段没有显式 field ID。Fory 会按源码声明顺序分配字段号,从 `1` 开始。 -### Scalar Type Mapping +### 标量类型映射 | FlatBuffers | Fory Type | | ----------- | --------- | @@ -88,14 +78,14 @@ source declaration order, starting at `1`. | `bool` | `bool` | | `string` | `string` | -Vectors (`[T]`) map to Fory lists. +向量(`[T]`)映射为 Fory 列表类型。 -### Unions +### 联合类型 -FlatBuffers unions map to Fory unions. +FlatBuffers union 映射为 Fory union。 -- Case IDs are assigned by declaration order, starting at `1`. -- Case names are derived from type names using snake_case field naming. +- case ID 按声明顺序分配,从 `1` 开始。 +- case 名称由类型名转换为 snake_case 字段名。 **FlatBuffers** @@ -110,7 +100,7 @@ table Container { } ``` -**Fory shape after translation** +**转换后的 Fory 结构** ```protobuf union Payload { @@ -123,33 +113,31 @@ message Container { } ``` -### Defaults and Metadata +### 默认值与元数据 -- FlatBuffers default values are parsed but not applied as Fory runtime defaults. -- Non-Fory metadata attributes are preserved as generic options in IR and may be - consumed by downstream tooling. +- FlatBuffers 默认值会被解析,但不会作为 Fory 运行时默认值生效。 +- 非 Fory 的 metadata 属性会作为通用 option 保留在 IR 中,供下游工具按需消费。 -## Fory-Specific Attributes in FlatBuffers +## FlatBuffers 中的 Fory 扩展属性 -FlatBuffers metadata attributes use `key:value`. For Fory-specific options, use -`fory_` (or `fory.`) prefix in `.fbs`; the prefix is removed during parsing. +FlatBuffers metadata 属性写法为 `key:value`。对于 Fory 扩展选项,在 `.fbs` 中使用 `fory_`(或 `fory.`)前缀;解析时会去掉该前缀。 -### Supported Field Attributes +### 支持的字段属性 -| FlatBuffers Attribute | Effect in Fory | -| -------------------------------- | ----------------------------------------------------- | -| `fory_ref:true` | Enable reference tracking for the field | -| `fory_nullable:true` | Mark field optional/nullable | -| `fory_weak_ref:true` | Enable weak reference semantics and implies `ref` | -| `fory_thread_safe_pointer:false` | For ref fields, select non-thread-safe pointer flavor | +| FlatBuffers Attribute | 在 Fory 中的效果 | +| -------------------------------- | --------------------------------- | +| `fory_ref:true` | 为字段启用引用跟踪 | +| `fory_nullable:true` | 将字段标记为 optional/nullable | +| `fory_weak_ref:true` | 启用弱引用语义,并隐含开启 `ref` | +| `fory_thread_safe_pointer:false` | 对 ref 字段选择非线程安全指针类型 | -Semantics: +语义说明: -- `fory_weak_ref:true` implies `ref`. -- `fory_thread_safe_pointer` only takes effect when the field is ref-tracked. -- For list fields, `fory_ref:true` applies to list elements. +- `fory_weak_ref:true` 隐含 `ref`。 +- `fory_thread_safe_pointer` 仅在字段启用 ref 跟踪时生效。 +- 对列表字段,`fory_ref:true` 作用于列表元素。 -Example: +示例: ```fbs table Node { @@ -159,42 +147,37 @@ table Node { } ``` -## Generated Code Differences +## 生成代码差异 -Using `.fbs` as input to Fory still produces normal Fory-generated code, not -FlatBuffers `ByteBuffer`-style APIs. +即使用 `.fbs` 作为 Fory 输入,生成的依然是标准 Fory 代码,而不是 FlatBuffers 的 `ByteBuffer` 风格 API。 -- Java: POJOs/records with Fory metadata -- Python: dataclasses plus registration helpers -- Go/Rust/C++: native structs and Fory metadata +- Java:带 Fory 元数据的 POJO/record +- Python:dataclass 与注册辅助代码 +- Go/Rust/C++:原生结构体与 Fory 元数据 -The serialization format is Fory binary protocol, not FlatBuffers wire format. +最终序列化格式是 Fory 二进制协议,而不是 FlatBuffers 线格式。 -## Usage +## 用法 -Compile a FlatBuffers schema directly: +直接编译 FlatBuffers schema: ```bash foryc schema.fbs --lang java,python --output ./generated ``` -Inspect translated schema syntax for debugging: +输出转换后的 Fory schema 语法以便调试: ```bash foryc schema.fbs --emit-fdl --emit-fdl-path ./translated ``` -## Migration Notes +## 迁移注意事项 -1. Keep existing `namespace` values stable to keep type registration stable. -2. Review fields that relied on FlatBuffers default literals and set explicit - defaults in application code if needed. -3. Add `fory_ref`/`fory_weak_ref` where object-graph semantics are required. -4. Validate generated model behavior with roundtrip tests before replacing - existing serialization paths. +1. 保持现有 `namespace` 稳定,以保证类型注册稳定。 +2. 检查依赖 FlatBuffers 字面量默认值的字段,并在业务代码中补充显式默认值。 +3. 在需要对象图语义的字段上添加 `fory_ref`/`fory_weak_ref`。 +4. 替换现有序列化路径前,先用 roundtrip 测试验证生成模型行为。 -## Summary +## 总结 -FlatBuffers input lets you reuse existing `.fbs` schemas while moving to Fory's -runtime and code generation model. This is useful for incremental migration, -while preserving schema investment and adopting Fory-native object APIs. +FlatBuffers 输入模式可让你复用现有 `.fbs` schema,同时迁移到 Fory 运行时与代码生成模型。它适合渐进式迁移场景:既保留既有 schema 投入,又能采用 Fory 原生对象 API。 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/generated-code.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/generated-code.md index ce33bac1e9..cadf241ab8 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/generated-code.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/generated-code.md @@ -19,20 +19,18 @@ license: | limitations under the License. --- -> 中文导读:本文档为 Fory 编译器/协议规范文档的中文译稿。为避免改变规范语义,代码片段、类型名、协议字段名保持英文,说明性文字优先翻译为中文。 +本文档说明各目标语言的代码生成结果与结构。 -本文档说明各目标语言的生成代码结构。 +Fory IDL 生成的类型遵循宿主语言习惯,可直接作为领域对象使用。生成代码同时包含 `to/from bytes` 辅助方法和类型注册辅助逻辑。 -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 registration helpers. +## 参考 Schema -## Reference Schemas +下面示例基于两个真实 schema: -The examples below use two real schemas: +1. `addressbook.fdl`(显式类型 ID) +2. `auto_id.fdl`(未显式声明类型 ID) -1. `addressbook.fdl` (explicit type IDs) -2. `auto_id.fdl` (no explicit type IDs) - -### `addressbook.fdl` (excerpt) +### `addressbook.fdl`(节选) ```protobuf package addressbook; @@ -79,7 +77,7 @@ message AddressBook [id=103] { } ``` -### `auto_id.fdl` (excerpt) +### `auto_id.fdl`(节选) ```protobuf package auto_id; @@ -114,17 +112,17 @@ union Wrapper { ## Java -### Output Layout +### 输出布局 -For `package addressbook`, Java output is generated under: +对于 `package addressbook`,Java 输出通常位于: - `/addressbook/` -- Type files: `AddressBook.java`, `Person.java`, `Dog.java`, `Cat.java`, `Animal.java` -- Registration helper: `AddressbookForyRegistration.java` +- 类型文件:`AddressBook.java`、`Person.java`、`Dog.java`、`Cat.java`、`Animal.java` +- 注册辅助类:`AddressbookForyRegistration.java` -### Type Generation +### 类型生成 -Messages generate Java classes with `@ForyField`, default constructors, getters/setters, and byte helpers: +message 会生成带 `@ForyField`、默认构造器、getter/setter 以及字节辅助方法的 Java 类: ```java public class Person { @@ -156,7 +154,7 @@ public class Person { } ``` -Unions generate classes extending `org.apache.fory.type.union.Union`: +union 会生成继承 `org.apache.fory.type.union.Union` 的类: ```java public final class Animal extends Union { @@ -177,9 +175,9 @@ public final class Animal extends Union { } ``` -### Registration +### 注册 -Generated registration helper: +生成的注册辅助方法: ```java public static void register(Fory fory) { @@ -194,7 +192,7 @@ public static void register(Fory fory) { } ``` -For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs (for example from `auto_id.fdl`): +对于未显式 `[id=...]` 的 schema,注册代码会使用计算得到的数值 ID(例如 `auto_id.fdl`): ```java resolver.register(Status.class, 1124725126L); @@ -204,7 +202,7 @@ resolver.registerUnion(Envelope.Detail.class, 1609214087L, new org.apache.fory.s resolver.register(Envelope.Payload.class, 2862577837L); ``` -If `option enable_auto_type_id = false;` is set, registration uses namespace and type name: +若设置 `option enable_auto_type_id = false;`,则按命名空间与类型名注册: ```java resolver.register(Config.class, "myapp.models", "Config"); @@ -215,7 +213,7 @@ resolver.registerUnion( new org.apache.fory.serializer.UnionSerializer(fory, Holder.class)); ``` -### Usage +### 使用示例 ```java Person person = new Person(); @@ -228,15 +226,15 @@ Person restored = Person.fromBytes(data); ## Python -### Output Layout +### 输出布局 -Python output is one module per schema file, for example: +Python 每个 schema 文件生成一个模块,例如: - `/addressbook.py` -### Type Generation +### 类型生成 -Unions generate a case enum plus a `Union` subclass with typed helpers: +union 生成 case 枚举与 `Union` 子类,并提供类型化辅助方法: ```python class AnimalCase(Enum): @@ -255,7 +253,7 @@ class Animal(Union): def set_dog(self, v: Dog) -> None: ... ``` -Messages generate `@pyfory.dataclass` types, and nested types stay nested: +message 生成 `@pyfory.dataclass` 类型,嵌套类型保持嵌套: ```python @pyfory.dataclass @@ -279,9 +277,9 @@ class Person: def from_bytes(cls, data: bytes) -> "Person": ... ``` -### Registration +### 注册 -Generated registration function: +生成注册函数: ```python def register_addressbook_types(fory: pyfory.Fory): @@ -294,7 +292,7 @@ def register_addressbook_types(fory: pyfory.Fory): fory.register_type(AddressBook, type_id=103) ``` -For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs: +未显式 `[id=...]` 时,注册代码使用计算得到的数值 ID: ```python fory.register_type(Status, type_id=1124725126) @@ -304,7 +302,7 @@ fory.register_union(Envelope.Detail, type_id=1609214087, serializer=Envelope.Det fory.register_type(Envelope.Payload, type_id=2862577837) ``` -If `option enable_auto_type_id = false;` is set: +若设置 `option enable_auto_type_id = false;`: ```python fory.register_type(Config, namespace="myapp.models", typename="Config") @@ -316,7 +314,7 @@ fory.register_union( ) ``` -### Usage +### 使用示例 ```python person = Person(name="Alice", pet=Animal.dog(Dog(name="Rex", bark_volume=10))) @@ -327,15 +325,15 @@ restored = Person.from_bytes(data) ## Rust -### Output Layout +### 输出布局 -Rust output is one module file per schema, for example: +Rust 每个 schema 生成一个模块文件,例如: - `/addressbook.rs` -### Type Generation +### 类型生成 -Unions map to Rust enums with `#[fory(id = ...)]` case attributes: +union 映射为 Rust enum,并用 `#[fory(id = ...)]` 声明 case ID: ```rust #[derive(ForyObject, Debug, Clone, PartialEq)] @@ -347,7 +345,7 @@ pub enum Animal { } ``` -Nested types generate nested modules: +嵌套类型生成嵌套 module: ```rust pub mod person { @@ -370,7 +368,7 @@ pub mod person { } ``` -Messages derive `ForyObject` and include `to_bytes`/`from_bytes` helpers: +message 会 `derive(ForyObject)` 并生成 `to_bytes`/`from_bytes`: ```rust #[derive(ForyObject, Debug, Clone, PartialEq, Default)] @@ -384,9 +382,9 @@ pub struct Person { } ``` -### Registration +### 注册 -Generated registration function: +生成注册函数: ```rust pub fn register_types(fory: &mut Fory) -> Result<(), fory::Error> { @@ -401,7 +399,7 @@ pub fn register_types(fory: &mut Fory) -> Result<(), fory::Error> { } ``` -For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs: +未显式 `[id=...]` 时,注册代码使用计算得到的数值 ID: ```rust fory.register::(1124725126)?; @@ -411,14 +409,14 @@ fory.register_union::(1609214087)?; fory.register::(2862577837)?; ``` -If `option enable_auto_type_id = false;` is set: +若设置 `option enable_auto_type_id = false;`: ```rust fory.register_by_namespace::("myapp.models", "Config")?; fory.register_union_by_namespace::("myapp.models", "Holder")?; ``` -### Usage +### 使用示例 ```rust let person = Person { @@ -433,15 +431,15 @@ let restored = Person::from_bytes(&bytes)?; ## C++ -### Output Layout +### 输出布局 -C++ output is one header per schema file, for example: +C++ 每个 schema 文件生成一个头文件,例如: - `/addressbook.h` -### Type Generation +### 类型生成 -Messages generate `final` classes with typed accessors and byte helpers: +message 会生成 `final` 类,并包含类型化访问器与字节辅助方法: ```cpp class Person final { @@ -467,7 +465,7 @@ class Person final { }; ``` -Optional message fields generate `has_xxx`, `mutable_xxx`, and `clear_xxx` APIs: +可选 message 字段会生成 `has_xxx`、`mutable_xxx`、`clear_xxx` API: ```cpp class Envelope final { @@ -487,7 +485,7 @@ class Envelope final { }; ``` -Unions generate `std::variant` wrappers: +union 会生成基于 `std::variant` 的封装: ```cpp class Animal final { @@ -517,11 +515,11 @@ class Animal final { }; ``` -Generated headers also include `FORY_UNION`, `FORY_FIELD_CONFIG`, `FORY_ENUM`, and `FORY_STRUCT` macros for serialization metadata. +生成头文件还会包含 `FORY_UNION`、`FORY_FIELD_CONFIG`、`FORY_ENUM`、`FORY_STRUCT` 等序列化元信息宏。 -### Registration +### 注册 -Generated registration function: +生成注册函数: ```cpp inline void register_types(fory::serialization::BaseFory& fory) { @@ -535,7 +533,7 @@ inline void register_types(fory::serialization::BaseFory& fory) { } ``` -For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs: +未显式 `[id=...]` 时,注册代码使用计算得到的数值 ID: ```cpp fory.register_enum(1124725126); @@ -545,14 +543,14 @@ fory.register_union(1609214087); fory.register_struct(2862577837); ``` -If `option enable_auto_type_id = false;` is set: +若设置 `option enable_auto_type_id = false;`: ```cpp fory.register_struct("myapp.models", "Config"); fory.register_union("myapp.models", "Holder"); ``` -### Usage +### 使用示例 ```cpp addressbook::Person person; @@ -565,17 +563,17 @@ auto restored = addressbook::Person::from_bytes(bytes.value()); ## Go -### Output Layout +### 输出布局 -Go output path depends on schema options and `--go_out`. +Go 输出路径受 schema 选项与 `--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). +对于 `addressbook.fdl`,若配置了 `go_package`,生成结果会遵循对应 import path/package(位于 `--go_out` 根目录下)。 -Without `go_package`, output uses the requested `--go_out` directory and package-derived file naming. +若未配置 `go_package`,则使用 `--go_out` 指定目录,并按 package 规则生成文件名与包名。 -### Type Generation +### 类型生成 -Nested types use underscore naming by default (`Person_PhoneType`, `Person_PhoneNumber`): +嵌套类型默认使用下划线命名(`Person_PhoneType`、`Person_PhoneNumber`): ```go type Person_PhoneType int32 @@ -592,7 +590,7 @@ type Person_PhoneNumber struct { } ``` -Messages generate structs with `fory` tags and byte helpers: +message 会生成带 `fory` tag 的 struct 与字节辅助方法: ```go type Person struct { @@ -606,7 +604,7 @@ func (m *Person) ToBytes() ([]byte, error) { ... } func (m *Person) FromBytes(data []byte) error { ... } ``` -Unions generate typed case structs with constructors/accessors/visitor APIs: +union 会生成 case struct,并提供构造器/访问器/visitor API: ```go type AnimalCase uint32 @@ -624,9 +622,9 @@ func (u Animal) AsDog() (*Dog, bool) { ... } func (u Animal) Visit(visitor AnimalVisitor) error { ... } ``` -### Registration +### 注册 -Generated registration function: +生成注册函数: ```go func RegisterTypes(f *fory.Fory) error { @@ -646,7 +644,7 @@ func RegisterTypes(f *fory.Fory) error { } ``` -For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs: +未显式 `[id=...]` 时,注册代码使用计算得到的数值 ID: ```go if err := f.RegisterEnum(Status(0), 1124725126); err != nil { ... } @@ -656,20 +654,20 @@ if err := f.RegisterUnion(Envelope_Detail{}, 1609214087, fory.NewUnionSerializer if err := f.RegisterStruct(Envelope_Payload{}, 2862577837); err != nil { ... } ``` -If `option enable_auto_type_id = false;` is set: +若设置 `option enable_auto_type_id = false;`: ```go if err := f.RegisterNamedStruct(Config{}, "myapp.models.Config"); err != nil { ... } if err := f.RegisterNamedUnion(Holder{}, "myapp.models.Holder", fory.NewUnionSerializer(...)); err != nil { ... } ``` -`go_nested_type_style` controls nested type naming: +`go_nested_type_style` 可控制嵌套类型命名风格: ```protobuf option go_nested_type_style = "camelcase"; ``` -### Usage +### 使用示例 ```go person := &Person{ @@ -687,30 +685,30 @@ if err := restored.FromBytes(data); err != nil { } ``` -## Cross-Language Notes +## 跨语言说明 -### Type ID Behavior +### 类型 ID 行为 -- Explicit `[id=...]` values are used directly in generated registration. -- 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 registration uses namespace/type-name APIs instead of numeric IDs. +- 显式 `[id=...]` 会直接用于生成注册代码。 +- 未声明类型 ID 时,生成代码会使用计算得到的数值 ID(参见 `auto_id.*` 输出)。 +- 若设置 `option enable_auto_type_id = false;`,则生成代码改为使用 namespace/type-name 注册 API,而非数值 ID。 -### Nested Type Shape +### 嵌套类型形态 -| Language | Nested type form | -| -------- | ------------------------------ | -| Java | `Person.PhoneNumber` | -| Python | `Person.PhoneNumber` | -| Rust | `person::PhoneNumber` | -| C++ | `Person::PhoneNumber` | -| Go | `Person_PhoneNumber` (default) | +| 语言 | 嵌套类型形式 | +| ------ | ---------------------------- | +| Java | `Person.PhoneNumber` | +| Python | `Person.PhoneNumber` | +| Rust | `person::PhoneNumber` | +| C++ | `Person::PhoneNumber` | +| Go | `Person_PhoneNumber`(默认) | -### Byte Helper Naming +### 字节辅助方法命名 -| Language | Helpers | -| -------- | ------------------------- | -| Java | `toBytes` / `fromBytes` | -| Python | `to_bytes` / `from_bytes` | -| Rust | `to_bytes` / `from_bytes` | -| C++ | `to_bytes` / `from_bytes` | -| Go | `ToBytes` / `FromBytes` | +| 语言 | 辅助方法名称 | +| ------ | ------------------------- | +| Java | `toBytes` / `fromBytes` | +| Python | `to_bytes` / `from_bytes` | +| Rust | `to_bytes` / `from_bytes` | +| C++ | `to_bytes` / `from_bytes` | +| Go | `ToBytes` / `FromBytes` | diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/index.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/index.md index 58a4817492..8e26cdd387 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/index.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/index.md @@ -19,15 +19,12 @@ license: | limitations under the License. --- -> 中文导读:本文档为 Fory 编译器/协议规范文档的中文译稿。为避免改变规范语义,代码片段、类型名、协议字段名保持英文,说明性文字优先翻译为中文。 - -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, Go, Rust, and C++. +Fory IDL 是 Apache Fory 的 Schema 定义语言,可实现类型安全的跨语言序列化。 +你只需定义一次数据结构,即可为 Java、Python、Go、Rust 和 C++ 生成原生数据结构代码。 ## 示例 Schema -Fory IDL provides a simple, intuitive syntax for defining cross-language data structures: +Fory IDL 提供了简单直观的语法来定义跨语言数据结构: ```protobuf package example; @@ -73,54 +70,54 @@ union Animal [id=106] { } ``` -## Why Fory IDL? +## 为什么选择 Fory IDL? -### Schema-First Development +### Schema 优先开发 -Define your data model once in Fory IDL and generate consistent, type-safe code across all languages. This ensures: +在 Fory IDL 中一次定义数据模型,即可在所有语言中生成一致且类型安全的代码。这样可以确保: -- **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 +- **类型安全**:在编译期而不是运行期发现类型错误 +- **一致性**:各语言使用相同字段名、类型和结构 +- **文档性**:Schema 本身就是可持续演进的文档 +- **可演进性**:可在所有实现中受控地进行 Schema 变更 -### Fory-Native Features +### Fory 原生能力 -Unlike generic IDLs, Fory IDL is designed specifically for Fory serialization: +与通用 IDL 不同,Fory IDL 专门为 Fory 序列化设计: -- **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 +- **引用跟踪**:通过 `ref` 一等支持共享引用和循环引用 +- **可空字段**:通过 `optional` 显式声明可空类型 +- **类型注册**:内置支持数值 ID 与基于命名空间的注册 +- **原生代码生成**:生成带 Fory 注解/宏的语言惯用代码 -### Low Integration 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 +- Java:带 `@ForyField` 注解的普通 POJO +- Python:带类型提示的 dataclass +- Go:带 struct tag 的结构体 +- Rust:带 `#[derive(ForyObject)]` 的结构体 +- C++:带 `FORY_STRUCT` 宏的结构体 -## Quick Start +## 快速开始 -### 1. Install the Compiler +### 1. 安装编译器 ```bash pip install fory-compiler ``` -Or install from source: +或从源码安装: ```bash cd compiler pip install -e . ``` -### 2. Write Your Schema +### 2. 编写 Schema -Create `example.fdl`: +创建 `example.fdl`: ```protobuf package example; @@ -132,19 +129,19 @@ message Person { } ``` -### 3. Generate Code +### 3. 生成代码 ```bash -# Generate for all languages +# 为所有语言生成 foryc example.fdl --output ./generated -# Generate for specific languages +# 为指定语言生成 foryc example.fdl --lang java,python --output ./generated ``` -### 4. Use Generated Code +### 4. 使用生成代码 -**Java:** +**Java:** ```java Person person = new Person(); @@ -153,34 +150,34 @@ person.setAge(30); byte[] data = person.toBytes(); ``` -**Python:** +**Python:** ```python import pyfory from example import Person person = Person(name="Alice", age=30) -data = bytes(person) # or `person.to_bytes()` +data = bytes(person) # 或 `person.to_bytes()` ``` -## Documentation +## 文档导航 -| Document | Description | -| ----------------------------------------------- | ------------------------------------------------- | -| [Fory IDL Syntax](schema-idl.md) | Complete language syntax and grammar | -| [Type System](schema-idl.md#type-system) | 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 IDL Support](protobuf-idl.md) | Comparison with protobuf and migration guide | -| [FlatBuffers IDL Support](flatbuffers-idl.md) | FlatBuffers mapping rules and codegen differences | +| 文档 | 说明 | +| -------------------------------------------- | ---------------------------------- | +| [Fory IDL 语法](schema-idl.md) | 完整语言语法与文法 | +| [类型系统](schema-idl.md#type-system) | 基础类型、集合类型与类型规则 | +| [编译器指南](compiler-guide.md) | CLI 选项与构建集成 | +| [生成代码](generated-code.md) | 各目标语言的输出格式 | +| [Protocol Buffers IDL 支持](protobuf-idl.md) | 与 protobuf 的对比及迁移指南 | +| [FlatBuffers IDL 支持](flatbuffers-idl.md) | FlatBuffers 映射规则与代码生成差异 | -## Key Concepts +## 核心概念 -### Field Modifiers +### 字段修饰符 -- **`optional`**: Field can be null/None -- **`ref`**: Enable reference tracking for shared/circular references -- **`list`**: Field is a list/array (alias: `repeated`) +- **`optional`**:字段可为 null/None +- **`ref`**:为共享/循环引用启用引用跟踪 +- **`list`**:字段为列表/数组(别名:`repeated`) ```protobuf message Example { @@ -190,26 +187,26 @@ message Example { } ``` -### Cross-Language Compatibility +### 跨语言兼容 -Fory IDL types map to native types in each language: +Fory IDL 类型会映射为各语言原生类型: -| Fory IDL Type | Java | Python | Go | Rust | C++ | +| Fory IDL 类型 | Java | Python | Go | Rust | C++ | | ------------- | --------- | -------------- | -------- | -------- | ------------- | | `int32` | `int` | `pyfory.int32` | `int32` | `i32` | `int32_t` | | `string` | `String` | `str` | `string` | `String` | `std::string` | | `bool` | `boolean` | `bool` | `bool` | `bool` | `bool` | -See [Type System](schema-idl.md#type-system) for complete mappings. +完整映射请参见 [类型系统](schema-idl.md#type-system)。 -## 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 +1. **使用有意义的 package 名称**:将相关类型分组管理 +2. **为性能分配类型 ID**:数值 ID 比基于名称的注册更高效 +3. **预留 ID 范围**:为后续扩展保留空隙(例如用户 100-199,订单 200-299) +4. **显式使用 `optional`**:清晰表达可空语义 +5. **共享对象使用 `ref`**:对象可能被多处引用时开启引用跟踪 -## Examples +## 示例 -See the [examples](https://github.com/apache/fory/tree/main/compiler/examples) directory for complete working examples. +完整可运行示例见 [examples](https://github.com/apache/fory/tree/main/compiler/examples) 目录。 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/protobuf-idl.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/protobuf-idl.md index 2a6865d1e2..d5bb1d8791 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/protobuf-idl.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/protobuf-idl.md @@ -19,56 +19,50 @@ license: | limitations under the License. --- -> 中文导读:本文档为 Fory 编译器/协议规范文档的中文译稿。为避免改变规范语义,代码片段、类型名、协议字段名保持英文,说明性文字优先翻译为中文。 - 本页说明 Apache Fory 如何处理 Protocol Buffers(`.proto`)schema、protobuf 概念如何映射到 Fory,以及 protobuf 专用 Fory 扩展选项的使用方式。 ## 本页内容 -- Choosing protobuf vs Fory for your use case -- Syntax and semantic differences that matter during migration -- Supported Fory extension options in protobuf files -- Practical migration patterns from protobuf to Fory +- 如何在具体场景下选择 protobuf 或 Fory +- 迁移时需要关注的语法与语义差异 +- `.proto` 文件中支持的 Fory 扩展选项 +- 从 protobuf 迁移到 Fory 的实践路径 ## 快速决策指南 -| Situation | Recommended Format | -| ------------------------------------------------------------- | ------------------ | -| You are building gRPC APIs and rely on protobuf tooling | Protocol Buffers | -| You need maximum object-graph performance and ref tracking | Fory | -| You need circular/shared references in serialized data | Fory | -| You need strong unknown-field behavior for wire compatibility | Protocol Buffers | -| You need native structs/classes instead of protobuf wrappers | Fory | +| 场景 | 建议格式 | +| ----------------------------------------------------- | ---------------- | +| 主要构建 gRPC API,依赖 protobuf 工具链 | Protocol Buffers | +| 需要极致对象图性能与引用跟踪 | Fory | +| 需要在序列化数据中表达循环/共享引用 | Fory | +| 需要强 unknown-field 语义保证线格式兼容 | Protocol Buffers | +| 希望直接使用原生 struct/class,而非 protobuf 包装类型 | Fory | ## Protobuf 与 Fory 对比 -| 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 | In progress (active development) | +| 维度 | Protocol Buffers | Fory | +| --------- | --------------------- | ---------------------- | +| 主要目标 | RPC/消息契约 | 高性能对象序列化 | +| 编码模型 | Tag-Length-Value | Fory 二进制协议 | +| 引用跟踪 | 非内建 | 一等支持(`ref`) | +| 循环引用 | 不支持 | 支持 | +| 未知字段 | 保留 | 不保留 | +| 生成类型 | protobuf 专用模型类型 | 语言原生构造 | +| gRPC 生态 | 原生成熟 | 持续建设中(活跃开发) | -Fory gRPC support is under active development. For production gRPC -workflows today, protobuf remains the mature/default choice. +Fory 的 gRPC 支持仍在持续开发中。当前生产级 gRPC 工作流里,protobuf 仍是更成熟的默认选择。 ## 为什么使用 Apache Fory -- Idiomatic generated code: Fory IDL generates language-idiomatic classes and - structs that can be used directly as domain objects. -- Faster serialization: In Fory benchmarks, Fory can be around 10x faster than - protobuf for object serialization workloads. -- Better graph modeling: Shared and circular references are first-class features - instead of application-level ID-link workarounds. +- **代码更贴近语言习惯**:Fory IDL 生成的类和结构体可直接作为业务领域对象使用。 +- **序列化性能更高**:在 Fory 基准中,Fory 在对象序列化场景中可显著快于 protobuf。 +- **对象图表达更自然**:共享引用和循环引用是内建能力,无需通过业务层 ID 关联绕过。 -See benchmark details under [Performance References](#performance-references). +性能细节请参见 [性能参考](#性能参考)。 -## Syntax and Semantic Mapping +## 语法与语义映射 -### Package and File Options +### Package 与文件级选项 **Protocol Buffers** @@ -85,10 +79,9 @@ option go_package = "example.com/models"; package example.models; ``` -Fory uses one package namespace for cross-language registration. Language-specific -package placement is still configurable in code generation. +Fory 使用统一 package 命名空间做跨语言注册。语言特定的包路径仍可在代码生成阶段单独配置。 -### Message and Enum Definitions +### Message 与 Enum 定义 **Protocol Buffers** @@ -126,16 +119,15 @@ enum Status [id=102] { } ``` -Key differences: +关键差异: -- Fory can assign stable type IDs directly (`[id=...]`). -- Fory uses `list` (with `repeated T` as alias). -- Enum naming conventions are language-driven instead of protobuf prefix style. +- Fory 可直接分配稳定类型 ID(`[id=...]`)。 +- Fory 使用 `list`(`repeated T` 为兼容别名)。 +- 枚举命名更偏向语言习惯,而非 protobuf 前缀风格。 -### `oneof` to `union` +### `oneof` 到 `union` -Protobuf `oneof` is translated to a nested Fory `union` plus an optional field -referencing that union. +protobuf 的 `oneof` 会被翻译为嵌套 Fory `union`,并增加一个可选字段指向该 union。 **Protocol Buffers** @@ -148,7 +140,7 @@ message Event { } ``` -**Fory-style shape after translation** +**转换后的 Fory 结构** ```protobuf message Event { @@ -160,42 +152,42 @@ message Event { } ``` -Notes: +说明: -- Union case IDs are derived from the original `oneof` field numbers. -- The synthetic union field uses the smallest `oneof` case number. +- union case ID 来自原 `oneof` 字段号。 +- 自动生成的 union 引用字段使用 `oneof` 中最小字段号。 -### Imports and Well-Known Types +### Import 与 Well-Known Types -Protobuf imports are supported. Common well-known types map directly: +支持 protobuf import。常见 well-known types 会直接映射: - `google.protobuf.Timestamp` -> `timestamp` - `google.protobuf.Duration` -> `duration` - `google.protobuf.Any` -> `any` -## 类型映射 Highlights - -| Protobuf Type | Fory Mapping | -| ---------------------------------------- | ---------------------------------------- | -| `bool` | `bool` | -| `int32`, `uint32` | variable-length 32-bit integer kinds | -| `sint32` | zigzag 32-bit integer | -| `int64`, `uint64` | variable-length 64-bit integer kinds | -| `sint64` | zigzag 64-bit integer | -| `fixed32`, `fixed64` | fixed-width unsigned integer kinds | -| `sfixed32`, `sfixed64` | fixed-width signed integer kinds | -| `float`, `double` | `float32`, `float64` | -| `string`, `bytes` | `string`, `bytes` | -| `repeated T` | `list` | -| `map` | `map` | -| `optional T` | `optional T` | -| `oneof` | `union` + optional union reference field | -| `int64 [(fory).type = "tagged_int64"]` | `tagged_int64` encoding | -| `uint64 [(fory).type = "tagged_uint64"]` | `tagged_uint64` encoding | - -## Fory Extension Options (Protobuf) - -Fory-specific options in `.proto` use the `(fory).` prefix. +## 类型映射要点 + +| Protobuf Type | Fory 映射 | +| ---------------------------------------- | ----------------------------- | +| `bool` | `bool` | +| `int32`, `uint32` | 可变长 32 位整型家族 | +| `sint32` | zigzag 32 位整型 | +| `int64`, `uint64` | 可变长 64 位整型家族 | +| `sint64` | zigzag 64 位整型 | +| `fixed32`, `fixed64` | 定长无符号整型家族 | +| `sfixed32`, `sfixed64` | 定长有符号整型家族 | +| `float`, `double` | `float32`, `float64` | +| `string`, `bytes` | `string`, `bytes` | +| `repeated T` | `list` | +| `map` | `map` | +| `optional T` | `optional T` | +| `oneof` | `union` + 可选 union 引用字段 | +| `int64 [(fory).type = "tagged_int64"]` | `tagged_int64` 编码 | +| `uint64 [(fory).type = "tagged_uint64"]` | `tagged_uint64` 编码 | + +## Fory 扩展选项(Protobuf) + +`.proto` 文件中的 Fory 专用选项使用 `(fory).` 前缀。 ```protobuf option (fory).enable_auto_type_id = true; @@ -206,46 +198,46 @@ message TreeNode { } ``` -### File-Level Options +### 文件级选项 -| Option | Type | Description | -| ------------------------------------ | ------ | -------------------------------------------------------------- | -| `(fory).use_record_for_java_message` | bool | Generate Java records for all messages in this file | -| `(fory).polymorphism` | bool | Enable polymorphic serialization metadata by default | -| `(fory).enable_auto_type_id` | bool | Auto-generate type IDs when omitted (compiler default is true) | -| `(fory).evolving` | bool | Default schema-evolution behavior for messages | -| `(fory).go_nested_type_style` | string | Go nested naming style: `underscore` (default) or `camelcase` | +| 选项 | 类型 | 说明 | +| ------------------------------------ | ------ | --------------------------------------------------- | +| `(fory).use_record_for_java_message` | bool | 对该文件所有 message 生成 Java record | +| `(fory).polymorphism` | bool | 默认开启多态序列化元信息 | +| `(fory).enable_auto_type_id` | bool | 缺失时自动生成类型 ID(编译器默认 true) | +| `(fory).evolving` | bool | message 的默认 schema 演进行为 | +| `(fory).go_nested_type_style` | string | Go 嵌套命名风格:`underscore`(默认)或 `camelcase` | -### Message and Enum Options +### Message 与 Enum 级选项 -| Option | Applies To | Type | Description | -| ---------------------------- | ------------- | ------ | ---------------------------------------- | -| `(fory).id` | message, enum | int | Explicit type ID for registration | -| `(fory).alias` | message, enum | string | Alternate name used for auto-ID hashing | -| `(fory).evolving` | message | bool | Override file-level evolution setting | -| `(fory).use_record_for_java` | message | bool | Generate Java record for this message | -| `(fory).deprecated` | message, enum | bool | Mark type as deprecated | -| `(fory).namespace` | message | string | Override default package-based namespace | +| 选项 | 作用对象 | 类型 | 说明 | +| ---------------------------- | ------------- | ------ | ----------------------------- | +| `(fory).id` | message, enum | int | 显式类型 ID(用于注册) | +| `(fory).alias` | message, enum | string | 自动 ID 哈希使用的别名 | +| `(fory).evolving` | message | bool | 覆盖文件级演进设置 | +| `(fory).use_record_for_java` | message | bool | 为该 message 生成 Java record | +| `(fory).deprecated` | message, enum | bool | 标记类型为弃用 | +| `(fory).namespace` | message | string | 覆盖默认 package 命名空间 | -### Field-Level Options +### 字段级选项 -| Option | Type | Description | -| ---------------------------- | ------ | ------------------------------------------------------------ | -| `(fory).ref` | bool | Enable reference tracking for this field | -| `(fory).nullable` | bool | Treat field as nullable (`optional`) | -| `(fory).weak_ref` | bool | Generate weak pointer semantics (C++/Rust codegen) | -| `(fory).thread_safe_pointer` | bool | Rust pointer flavor for ref fields (`Arc` vs `Rc`) | -| `(fory).deprecated` | bool | Mark field as deprecated | -| `(fory).type` | string | Primitive override, currently `tagged_int64`/`tagged_uint64` | +| 选项 | 类型 | 说明 | +| ---------------------------- | ------ | ----------------------------------------------------- | +| `(fory).ref` | bool | 为该字段启用引用跟踪 | +| `(fory).nullable` | bool | 将字段视为可空(`optional`) | +| `(fory).weak_ref` | bool | 生成弱指针语义(C++/Rust 代码生成) | +| `(fory).thread_safe_pointer` | bool | ref 字段在 Rust 中的指针类型(`Arc` vs `Rc`) | +| `(fory).deprecated` | bool | 标记字段为弃用 | +| `(fory).type` | string | 基础类型覆盖,目前支持 `tagged_int64`/`tagged_uint64` | -Reference option behavior: +引用相关行为: -- `weak_ref = true` implies ref tracking. -- For `repeated` fields, `(fory).ref = true` applies to list elements. -- For `map` fields, `(fory).ref = true` applies to map values. -- `weak_ref` and `thread_safe_pointer` are codegen hints for C++/Rust. +- `weak_ref = true` 隐含开启 ref 跟踪。 +- 对 `repeated` 字段,`(fory).ref = true` 作用于列表元素。 +- 对 `map` 字段,`(fory).ref = true` 作用于 map value。 +- `weak_ref` 与 `thread_safe_pointer` 是 C++/Rust 代码生成提示。 -### Option Examples by Shape +### 典型选项组合示例 ```protobuf message Graph { @@ -256,12 +248,11 @@ message Graph { } ``` -## Reference Tracking vs Protobuf IDs +## 引用跟踪 vs Protobuf ID 关联 -Protobuf itself does not preserve shared/cyclic object graphs. With Fory -protobuf extensions, you can opt into graph semantics. +protobuf 本身不保留共享/循环对象图。借助 Fory protobuf 扩展,可以显式启用对象图语义。 -**Without Fory ref options (protobuf-style IDs):** +**不使用 Fory ref 选项(protobuf 风格 ID 关联):** ```protobuf message TreeNode { @@ -271,7 +262,7 @@ message TreeNode { } ``` -**With Fory ref options (object graph):** +**使用 Fory ref 选项(对象图语义):** ```protobuf message TreeNode { @@ -280,37 +271,34 @@ message TreeNode { } ``` -## Migration Guide: Protobuf to Fory +## 迁移指南:Protobuf 到 Fory -### Step 1: Translate Schema Syntax +### 第 1 步:转换 schema 语法 -- Keep package names stable. -- Replace `repeated T` with `list` (or keep `repeated` alias). -- Add explicit `[id=...]` where you need stable numeric registration. +- 保持 package 名称稳定。 +- 将 `repeated T` 改为 `list`(或保留 `repeated` 别名)。 +- 在需要稳定数值注册的位置添加显式 `[id=...]`。 -### Step 2: Convert `oneof` and Special Types +### 第 2 步:处理 `oneof` 与特殊类型 -- `oneof` -> `union` + optional union field. -- Map protobuf well-known types to Fory primitives (`timestamp`, `duration`, `any`). +- `oneof` -> `union` + 可选 union 字段。 +- 将 protobuf well-known types 映射到 Fory 基础类型(`timestamp`、`duration`、`any`)。 -### Step 3: Replace Protobuf Workarounds with `ref` +### 第 3 步:用 `ref` 替换 protobuf 的对象图绕过方案 -Where protobuf used manual ID links for object graphs, switch to Fory `ref` -modifiers (and optional `ref(weak=true)` where needed). +若 protobuf 里通过手工 ID 关联表达对象图,迁移到 Fory 后应改用 `ref` 修饰符(必要时使用 `ref(weak=true)`)。 -### Step 4: Update Build/Codegen +### 第 4 步:更新构建与代码生成 -Replace protobuf generation steps with the Fory compiler invocation for target -languages. +将 protobuf 代码生成步骤替换为 Fory 编译器针对目标语言的生成命令。 -### Step 5: Run Compatibility Checks +### 第 5 步:执行兼容性验证 -For staged migrations, keep both formats in parallel and verify payload-level -parity with integration tests. +分阶段迁移时,可并行保留两种格式,并通过集成测试验证 payload 级一致性。 -## Coexistence Strategy +## 共存策略 -You can run protobuf and Fory in parallel during migration: +迁移期间可以并行运行 protobuf 与 Fory: ```java public byte[] serialize(Object obj, Format format) { @@ -321,16 +309,13 @@ public byte[] serialize(Object obj, Format format) { } ``` -Use translators at service boundaries while internal object-graph heavy paths -migrate first. +可在服务边界设置转换层,并优先迁移内部对象图较重的链路。 -## Performance References +## 性能参考 - Benchmarks: https://fory.apache.org/docs/introduction/benchmark - Benchmark code: https://github.com/apache/fory/tree/main/benchmarks -## Summary +## 总结 -Use protobuf when your primary concern is API contracts and gRPC ecosystem -integration. Use Fory when object-graph performance, native models, and -reference semantics are the primary concern. +当主要关注 API 契约与 gRPC 生态时,建议使用 protobuf。若主要关注对象图性能、原生数据模型与引用语义,建议使用 Fory。 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/schema-idl.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/schema-idl.md index ee420bd790..be6d5c6b2a 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/schema-idl.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/compiler/schema-idl.md @@ -19,37 +19,19 @@ license: | limitations under the License. --- -## 中文章节导读 +本文档给出 Fory IDL 的语法与语义参考,覆盖文件结构、类型系统、字段规则、选项与类型注册策略。 -本文描述 Fory IDL 的语法与语义规则,覆盖文件结构、声明、类型定义、字段约束、注解与扩展选项。它是编译器前端解析与代码生成的基础约束文档。 - -阅读时可重点关注: - -1. **文件级结构**:package、option、import 与类型声明顺序。 -2. **类型系统语法**:enum/message/union 及字段声明规则。 -3. **字段标签与属性**:字段 ID、可空、引用、默认值与兼容性约束。 -4. **命名与作用域**:类型可见性、嵌套声明与名称解析。 -5. **与 protobuf/flatbuffers 的映射关系**:迁移与互操作规则。 - -为保证编译行为一致,语法关键字、示例 schema 与标识符保持英文;说明性段落使用中文。 - -> 中文导读:本文档为 Fory 编译器/协议规范文档的中文译稿。为避免改变规范语义,代码片段、类型名、协议字段名保持英文,说明性文字优先翻译为中文。 - -本文档提供 Fory IDL 的语法与语义参考。 - -For compiler usage and build integration, see -[Compiler Guide](compiler-guide.md). For protobuf/FlatBuffers frontend mapping -rules, see [Protocol Buffers IDL Support](protobuf-idl.md) and -[FlatBuffers IDL Support](flatbuffers-idl.md). +编译器使用方式与构建集成请参见 [Compiler Guide](compiler-guide.md)。 +protobuf/FlatBuffers 前端映射请参见 [Protocol Buffers IDL Support](protobuf-idl.md) 与 [FlatBuffers IDL Support](flatbuffers-idl.md)。 ## 文件结构 -An Fory IDL file typically consists of: +一个 Fory IDL 文件通常包含: -1. Optional package declaration -2. Optional file-level options -3. Optional import statements -4. Type definitions (enums, messages, and unions) +1. 可选 `package` 声明 +2. 可选文件级 `option` +3. 可选 `import` 语句 +4. 类型定义(`enum`、`message`、`union`) ```protobuf // Optional package declaration @@ -70,7 +52,7 @@ union Event [id=103] { ... } ## 注释 -Fory IDL supports both single-line and block comments: +支持单行注释与块注释: ```protobuf // This is a single-line comment @@ -85,51 +67,51 @@ message Example { } ``` -## Package Declaration +## Package 声明 -The package declaration defines the namespace for all types in the file. +`package` 定义文件中所有类型的命名空间。 ```protobuf package com.example.models; ``` -You can optionally specify a package alias used for auto-generated type IDs: +也可以配置 alias(用于自动类型 ID 计算): ```protobuf package com.example.models alias models_v1; ``` -**Rules:** +规则: -- Optional but recommended -- Must appear before any type definitions -- Only one package declaration per file -- Used for namespace-based type registration -- Package alias is used for auto-ID hashing +- 可选但推荐 +- 必须位于任何类型定义之前 +- 每个文件最多一个 `package` +- 用于命名空间注册 +- `alias` 会参与 auto-ID 哈希 -**Language Mapping:** +语言映射: -| Language | Package Usage | -| -------- | --------------------------------- | -| Java | Java package | -| Python | Module name (dots to underscores) | -| Go | Package name (last component) | -| Rust | Module name (dots to underscores) | -| C++ | Namespace (dots to `::`) | +| 语言 | package 用法 | +| ------ | ----------------------- | +| Java | Java package | +| Python | 模块名(`.` 转 `_`) | +| Go | 包名(通常取最后一段) | +| Rust | 模块名(`.` 转 `_`) | +| C++ | 命名空间(`.` 转 `::`) | -## File-Level Options +## 文件级选项 -Options can be specified at file level to control language-specific code generation. +文件级选项用于控制语言定制代码生成。 -### Syntax +### 语法 ```protobuf option option_name = value; ``` -### Java Package Option +### Java Package 选项 -Override the Java package for generated code: +通过 `java_package` 覆盖 Java 输出包名: ```protobuf package payment; @@ -140,15 +122,15 @@ message Payment { } ``` -**Effect:** +效果: -- Generated Java files will be in `com/mycorp/payment/v1/` directory -- Java package declaration will be `package com.mycorp.payment.v1;` -- Type registration still uses the Fory IDL package (`payment`) for cross-language compatibility +- Java 文件输出到 `com/mycorp/payment/v1/` +- Java `package` 声明使用该值 +- 跨语言类型注册仍以 Fory package(如 `payment`)为准 -### Go Package Option +### Go Package 选项 -Specify the Go import path and package name: +通过 `go_package` 指定 Go import path 与包名: ```protobuf package payment; @@ -159,17 +141,11 @@ message Payment { } ``` -**Format:** `"import/path;package_name"` or just `"import/path"` (last segment used as package name) - -**Effect:** - -- Generated Go files will have `package paymentv1` -- The import path can be used in other Go code -- Type registration still uses the Fory IDL package (`payment`) for cross-language compatibility +格式:`"import/path;package_name"` 或仅 `"import/path"`(包名取最后一段)。 -### Java Outer Classname Option +### Java Outer Classname 选项 -Generate all types as inner classes of a single outer wrapper class: +将多个类型包装到一个外层类: ```protobuf package payment; @@ -186,49 +162,11 @@ message Payment { } ``` -**Effect:** - -- Generates a single file `DescriptorProtos.java` instead of separate files -- All enums and messages become `public static` inner classes -- The outer class is `public final` with a private constructor -- Useful for grouping related types together - -**Generated structure:** - -```java -public final class DescriptorProtos { - private DescriptorProtos() {} - - public static enum Status { - UNKNOWN, - ACTIVE; - } - - public static class Payment { - private String id; - private Status status; - // ... - } -} -``` - -**Combined with java_package:** +默认会生成单文件,枚举与消息作为静态内部类型。 -```protobuf -package payment; -option java_package = "com.example.proto"; -option java_outer_classname = "PaymentProtos"; +### Java Multiple Files 选项 -message Payment { - string id = 1; -} -``` - -This generates `com/example/proto/PaymentProtos.java` with all types as inner classes. - -### Java Multiple Files Option - -Control whether types are generated in separate files or as inner classes: +控制 Java 是否拆分多文件: ```protobuf package payment; @@ -244,1171 +182,556 @@ message Receipt { } ``` -**Behavior:** - -| `java_outer_classname` | `java_multiple_files` | Result | -| ---------------------- | --------------------- | ------------------------------------------- | -| Not set | Any | Separate files (one per type) | -| Set | `false` (default) | Single file with all types as inner classes | -| Set | `true` | Separate files (overrides outer class) | +行为: -**Effect of `java_multiple_files = true`:** +| `java_outer_classname` | `java_multiple_files` | 结果 | +| ---------------------- | --------------------- | ---------------- | +| 未设置 | 任意 | 每个类型一个文件 | +| 已设置 | `false`(默认) | 单文件 + 内部类 | +| 已设置 | `true` | 强制拆分为多文件 | -- Each top-level enum and message gets its own `.java` file -- Overrides `java_outer_classname` behavior -- Useful when you want separate files but still specify an outer class name for other purposes - -**Example without java_multiple_files (default):** - -```protobuf -option java_outer_classname = "PaymentProtos"; -// Generates: PaymentProtos.java containing Payment and Receipt as inner classes -``` - -**Example with java_multiple_files = true:** - -```protobuf -option java_outer_classname = "PaymentProtos"; -option java_multiple_files = true; -// Generates: Payment.java, Receipt.java (separate files) -``` - -### Multiple Options - -Multiple options can be specified: +### 多个选项组合 ```protobuf package payment; option java_package = "com.mycorp.payment.v1"; option go_package = "github.com/mycorp/apis/gen/payment/v1;paymentv1"; option deprecated = true; - -message Payment { - string id = 1; -} ``` -### Protobuf Extension Syntax +### Protobuf 扩展语法说明 -In `.fdl` files, use native Fory IDL syntax only (for example, `[id=100]`, `ref`, -`optional`, `nullable=true`). +在 `.fdl` 中请使用 Fory 原生语法(如 `[id=100]`、`ref`、`optional`、`nullable=true`)。 +`(fory).xxx` 形式仅用于 `.proto`(protobuf 前端)。 -Protobuf extension syntax with `(fory).` is for `.proto` files and the protobuf -frontend only. +### 选项优先级 -For protobuf extension options, see -[Protocol Buffers IDL Support](protobuf-idl.md#fory-extension-options-protobuf). +语言包路径优先级: -### Option Priority +1. 命令行覆盖(最高) +2. 语言选项(`java_package`、`go_package`) +3. Fory IDL `package`(兜底) -For language-specific packages: +### 跨语言类型注册 -1. Command-line package override (highest priority) -2. Language-specific option (`java_package`, `go_package`) -3. Fory IDL package declaration (fallback) - -**Example:** - -```protobuf -package myapp.models; -option java_package = "com.example.generated"; -``` +默认情况下,注册名由 `package + type name`(或类型 ID)确定。建议长期保持 `package` 稳定,以避免跨版本注册不一致。 -| Scenario | Java Package Used | -| ------------------------- | ------------------------- | -| No override | `com.example.generated` | -| CLI: `--package=override` | `override` | -| No java_package option | `myapp.models` (fallback) | +## Import 语句 -### Cross-Language Type Registration - -Language-specific options only affect where code is generated, not the type namespace used for serialization. This ensures cross-language compatibility: - -```protobuf -package myapp.models; -option java_package = "com.mycorp.generated"; -option go_package = "github.com/mycorp/gen;genmodels"; - -message User { - string name = 1; -} -``` - -All languages will register `User` with namespace `myapp.models`, enabling: - -- Java serialized data → Go deserialization -- Go serialized data → Java deserialization -- Any language combination works seamlessly - -## Import Statement - -Import statements allow you to use types defined in other Fory IDL files. - -### Basic Syntax +### 基本语法 ```protobuf -import "path/to/file.fdl"; +import "common/types.fdl"; ``` -### Multiple Imports +### 多个导入 ```protobuf import "common/types.fdl"; -import "common/enums.fdl"; -import "models/address.fdl"; +import "domain/user.fdl"; +import "domain/order.fdl"; ``` -### Path Resolution +### 路径解析 -Import paths are resolved relative to the importing file: +导入解析顺序: -``` -project/ -├── common/ -│ └── types.fdl -├── models/ -│ ├── user.fdl # import "../common/types.fdl" -│ └── order.fdl # import "../common/types.fdl" -└── main.fdl # import "common/types.fdl" -``` +1. 导入者文件所在目录 +2. 命令行 `-I/--proto_path/--import_path` 指定目录(按给定顺序) -**Rules:** - -- Import paths are quoted strings (double or single quotes) -- Paths are resolved relative to the importing file's directory -- Imported types become available as if defined in the current file -- Circular imports are detected and reported as errors -- Transitive imports work (if A imports B and B imports C, A has access to C's types) - -### Complete Example - -**common/types.fdl:** +### 完整示例 ```protobuf -package common; +// src/main.fdl +package app; -enum Status [id=100] { - PENDING = 0; - ACTIVE = 1; - COMPLETED = 2; -} +import "common.fdl"; +import "models/user.fdl"; -message Address [id=101] { - string street = 1; - string city = 2; - string country = 3; +message Main { + common.Meta meta = 1; + models.User user = 2; } ``` -**models/user.fdl:** - -```protobuf -package models; -import "../common/types.fdl"; - -message User [id=200] { - string id = 1; - string name = 2; - Address home_address = 3; // Uses imported type - Status status = 4; // Uses imported enum -} -``` - -### Unsupported Import Syntax - -The following protobuf import modifiers are **not supported**: - -```protobuf -// NOT SUPPORTED - will produce an error -import public "other.fdl"; -import weak "other.fdl"; -``` +### 不支持的 import 写法 -**`import public`**: Fory IDL uses a simpler import model. All imported types are available to the importing file only. Re-exporting is not supported. Import each file directly where needed. +- URL 形式(如 `https://...`) +- 绝对路径依赖(不推荐,会破坏可移植性) -**`import weak`**: Fory IDL requires all imports to be present at compile time. Optional dependencies are not supported. +### import 错误 -### Import Errors +典型错误: -The compiler reports errors for: +- 文件不存在 +- 搜索路径未包含依赖目录 +- 同名文件冲突导致解析到错误版本 -- **File not found**: The imported file doesn't exist -- **Circular import**: A imports B which imports A (directly or indirectly) -- **Parse errors**: Syntax errors in imported files -- **Unsupported syntax**: `import public` or `import weak` +## Enum 定义 -## Enum Definition - -Enums define a set of named integer constants. - -### Basic Syntax +### 基本语法 ```protobuf enum Status { - PENDING = 0; + UNKNOWN = 0; ACTIVE = 1; - COMPLETED = 2; + DISABLED = 2; } ``` -### With Explicit Type ID +### 显式类型 ID ```protobuf -enum Status [id=100] { - PENDING = 0; +enum Status [id=101] { + UNKNOWN = 0; ACTIVE = 1; - COMPLETED = 2; + DISABLED = 2; } ``` -### Reserved Values - -Reserve field numbers or names to prevent reuse: +### 预留值 ```protobuf enum Status { - reserved 2, 15, 9 to 11, 40 to max; // Reserved numbers - reserved "OLD_STATUS", "DEPRECATED"; // Reserved names - PENDING = 0; - ACTIVE = 1; - COMPLETED = 3; -} -``` - -### Enum Type Options - -Enum-level options are declared inline in `[]` after the enum name: - -```protobuf -enum Status [deprecated=true] { - PENDING = 0; + UNKNOWN = 0; ACTIVE = 1; + reserved 2, 3; + reserved 10 to 20; } ``` -FDL does not support `option ...;` statements inside enum bodies. - -**Unsupported:** - -- `allow_alias` is **not supported**. Each enum value must have a unique integer. - -### Language Mapping - -| Language | Implementation | -| -------- | -------------------------------------- | -| Java | `enum Status { UNKNOWN, ACTIVE, ... }` | -| Python | `class Status(IntEnum): UNKNOWN = 0` | -| Go | `type Status int32` with constants | -| Rust | `#[repr(i32)] enum Status { Unknown }` | -| C++ | `enum class Status : int32_t { ... }` | - -### Enum Prefix Stripping - -When enum values use a protobuf-style prefix (enum name in UPPER_SNAKE_CASE), the compiler automatically strips the prefix for languages with scoped enums: - -```protobuf -// Input with prefix -enum DeviceTier { - DEVICE_TIER_UNKNOWN = 0; - DEVICE_TIER_TIER1 = 1; - DEVICE_TIER_TIER2 = 2; -} -``` - -**Generated code:** +### enum 类型选项 -| Language | Output | Style | -| -------- | ----------------------------------------- | -------------- | -| Java | `UNKNOWN, TIER1, TIER2` | Scoped enum | -| Rust | `Unknown, Tier1, Tier2` | Scoped enum | -| C++ | `UNKNOWN, TIER1, TIER2` | Scoped enum | -| Python | `UNKNOWN, TIER1, TIER2` | Scoped IntEnum | -| Go | `DeviceTierUnknown, DeviceTierTier1, ...` | Unscoped const | +常见:`id`、`alias`、`deprecated`。 -**Note:** The prefix is only stripped if the remainder is a valid identifier. For example, `DEVICE_TIER_1` is kept unchanged because `1` is not a valid identifier name. +### 语言映射 -**Grammar:** +- Java:`enum` +- Python:`IntEnum` +- Go:`type + const` +- Rust:`repr(i32)` 枚举 +- C++:`enum class` -``` -enum_def := 'enum' IDENTIFIER [type_options] '{' enum_body '}' -type_options := '[' type_option (',' type_option)* ']' -type_option := IDENTIFIER '=' option_value -enum_body := (reserved_stmt | enum_value)* -reserved_stmt := 'reserved' reserved_items ';' -enum_value := IDENTIFIER '=' INTEGER ';' -``` - -**Rules:** - -- Enum names must be unique within the file -- Enum values must have explicit integer assignments -- Value integers must be unique within the enum (no aliases) -- Type ID (`[id=100]`) is optional for enums but recommended for cross-language use - -**Example with All Features:** - -```protobuf -// HTTP status code categories -enum HttpCategory [id=200] { - reserved 10 to 20; // Reserved for future use - reserved "UNKNOWN"; // Reserved name - INFORMATIONAL = 1; - SUCCESS = 2; - REDIRECTION = 3; - CLIENT_ERROR = 4; - SERVER_ERROR = 5; -} -``` +### 枚举前缀处理 -## Message Definition +针对 protobuf 风格 `TYPE_NAME_VALUE`,生成器通常会按语言习惯去除冗余前缀,使 API 更自然。 -Messages define structured data types with typed fields. +## Message 定义 -### Basic Syntax +### 基本语法 ```protobuf -message Person { - string name = 1; - int32 age = 2; -} -``` - -### With Explicit Type ID - -```protobuf -message Person [id=101] { +message User { string name = 1; int32 age = 2; } ``` -### Without Explicit Type ID +### 显式类型 ID ```protobuf -message Person { // Auto-generated when enable_auto_type_id = true +message User [id=100] { string name = 1; int32 age = 2; } ``` -### Language Mapping +### 无显式类型 ID -| Language | Implementation | -| -------- | ----------------------------------- | -| Java | POJO class with getters/setters | -| Python | `@dataclass` class | -| Go | Struct with exported fields | -| Rust | Struct with `#[derive(ForyObject)]` | -| C++ | Struct with `FORY_STRUCT` macro | +未声明 `[id=...]` 时,编译器可按配置自动生成类型 ID,或使用 namespace/name 注册。 -Type IDs control cross-language registration for messages, unions, and enums. See -[Type IDs](#type-ids) for auto-generation, aliases, and collision handling. +### 语言映射 -### Reserved Fields +- Java:类 / record(按选项) +- Python:dataclass +- Go:struct +- Rust:struct +- C++:class/struct + 宏元信息 -Reserve field numbers or names to prevent reuse after removing fields: +### 预留字段 ```protobuf message User { - reserved 2, 15, 9 to 11; // Reserved field numbers - reserved "old_field", "temp"; // Reserved field names - string id = 1; - string name = 3; -} -``` - -### Message Type Options - -Message-level options are declared inline in `[]` after the message name: - -```protobuf -message User [deprecated=true] { - string id = 1; - string name = 2; + string name = 1; + reserved 2, 3; + reserved 10 to 20; } ``` -FDL does not support `option ...;` statements inside message or enum bodies. - -**Grammar:** - -``` -message_def := 'message' IDENTIFIER [type_options] '{' message_body '}' -type_options := '[' type_option (',' type_option)* ']' -type_option := IDENTIFIER '=' option_value -message_body := (reserved_stmt | nested_type | field_def)* -nested_type := enum_def | message_def | union_def -``` - -**Rules:** - -- Type IDs follow the rules in [Type IDs](#type-ids). +### message 类型选项 -## Nested Types +常见选项:`id`、`alias`、`evolving`、`deprecated`、`namespace`、`use_record_for_java`。 -Messages can contain nested message, enum, and union definitions. This is useful for defining types that are closely related to their parent message. +## 嵌套类型 -### Nested Messages +### 嵌套 message ```protobuf -message SearchResponse { - message Result { - string url = 1; - string title = 2; - list snippets = 3; - } - list results = 1; -} -``` - -### Nested Enums - -```protobuf -message Container { - enum Status { - STATUS_UNKNOWN = 0; - STATUS_ACTIVE = 1; - STATUS_INACTIVE = 2; +message Person { + message PhoneNumber { + string number = 1; } - Status status = 1; + PhoneNumber phone = 1; } ``` -### Qualified Type Names - -Nested types can be referenced from other messages using qualified names (Parent.Child): +### 嵌套 enum ```protobuf -message SearchResponse { - message Result { - string url = 1; - string title = 2; +message Person { + enum PhoneType { + MOBILE = 0; + HOME = 1; } -} - -message SearchResultCache { - // Reference nested type with qualified name - SearchResponse.Result cached_result = 1; - list all_results = 2; + PhoneType type = 1; } ``` -### Deeply Nested Types +### 限定类型名 -Nesting can be multiple levels deep: +可使用完整限定名引用嵌套类型,例如 `Person.PhoneNumber`。 -```protobuf -message Outer { - message Middle { - message Inner { - string value = 1; - } - Inner inner = 1; - } - Middle middle = 1; -} - -message OtherMessage { - // Reference deeply nested type - Outer.Middle.Inner deep_ref = 1; -} -``` +### 深层嵌套类型 -### Language-Specific Generation +支持多层嵌套,但建议控制层级,避免可读性下降。 -| Language | Nested Type Generation | -| -------- | --------------------------------------------------------------------------------- | -| Java | Static inner classes (`SearchResponse.Result`) | -| Python | Nested classes within dataclass | -| Go | Flat structs with underscore (`SearchResponse_Result`, configurable to camelcase) | -| Rust | Nested modules (`search_response::Result`) | -| C++ | Nested classes (`SearchResponse::Result`) | +### 各语言生成形态 -**Note:** Go defaults to underscore-separated nested names; set `option go_nested_type_style = "camelcase";` to use concatenated names. Rust emits nested modules for nested types. +| 语言 | 嵌套类型形态 | +| ------ | --------------------- | +| Java | `Outer.Inner` | +| Python | `Outer.Inner` | +| Rust | `outer::Inner` | +| C++ | `Outer::Inner` | +| Go | `Outer_Inner`(默认) | -### Nested Type Rules +### 嵌套规则 -- Nested type names must be unique within their parent message -- Nested types can have their own type IDs -- Numeric type IDs must be globally unique (including nested types); see [Type IDs](#type-ids) - for auto-generation and collision handling -- Within a message, you can reference nested types by simple name -- From outside, use the qualified name (Parent.Child) +- 嵌套类型名在其父作用域内必须唯一 +- 可被同文件后续类型引用 +- 可通过 import + 限定名跨文件引用 -## Union Definition +## Union 定义 -Unions define a value that can hold exactly one of several case types. - -### Basic Syntax +### 基本语法 ```protobuf -union Animal [id=106] { +union Animal { Dog dog = 1; Cat cat = 2; } ``` -### Using a Union in a Message +### 在 message 中使用 union ```protobuf -message Person [id=100] { +message Person { Animal pet = 1; - optional Animal favorite_pet = 2; } ``` -### Rules - -- Case IDs must be unique within the union -- Cases cannot be `optional` or `ref` -- Union cases do not support field options -- Case types can be primitives, enums, messages, or other named types -- Union type IDs follow the rules in [Type IDs](#type-ids). - -**Grammar:** +### 规则 -``` -union_def := 'union' IDENTIFIER [type_options] '{' union_field* '}' -union_field := field_type IDENTIFIER '=' INTEGER ';' -``` +- case 字段号必须唯一 +- case 类型通常为消息类型或可序列化复合类型 +- 各语言会生成带 case 判别和访问器的 union 表达 -## Field Definition +## 字段定义 -Fields define the properties of a message. - -### Basic Syntax +### 基本语法 ```protobuf -field_type field_name = field_number; +string name = 1; ``` -### With Modifiers +### 带修饰符语法 ```protobuf -optional list tags = 1; // Nullable list -list tags = 2; // Elements may be null -ref list nodes = 3; // Collection tracked as a reference -list nodes = 4; // Elements tracked as references +optional string nickname = 2; +ref Node parent = 3; +list scores = 4; ``` -**Grammar:** - -``` -field_def := [modifiers] field_type IDENTIFIER '=' INTEGER ';' -modifiers := { 'optional' | 'ref' } -field_type := primitive_type | named_type | list_type | map_type -list_type := 'list' '<' { 'optional' | 'ref' } field_type '>' -``` - -Modifiers apply to the field/collection. Use `list<...>` to describe element -modifiers. `repeated` is accepted as an alias for `list`. - -### Field Modifiers +### 字段修饰符 #### `optional` -Marks the field as nullable: +声明字段可为空(null/None): ```protobuf message User { - string name = 1; // Required, non-null - optional string email = 2; // Nullable + optional string email = 1; } ``` -**Generated Code:** - -| Language | Non-optional | Optional | -| -------- | ------------------ | ----------------------------------------------- | -| Java | `String name` | `String email` with `@ForyField(nullable=true)` | -| Python | `name: str` | `name: Optional[str]` | -| Go | `Name string` | `Name *string` | -| Rust | `name: String` | `name: Option` | -| C++ | `std::string name` | `std::optional name` | - -**Default Values:** - -| Type | Default Value | -| ------------------ | ------------------- | -| Non-optional types | Language default | -| Optional types | `null`/`None`/`nil` | +建议在跨语言场景显式使用,以避免默认值差异。 #### `ref` -Enables reference tracking for shared/circular references: +开启引用跟踪,用于共享对象与循环结构: ```protobuf message Node { - string value = 1; - ref Node parent = 2; // Can point to shared object + string name = 1; + ref Node parent = 2; list children = 3; } ``` -**Use Cases:** - -- Shared objects (same object referenced multiple times) -- Circular references (object graphs with cycles) -- Tree structures with parent pointers - -**Generated Code:** - -| Language | Without `ref` | With `ref` | -| -------- | -------------- | ----------------------------------------- | -| Java | `Node parent` | `Node parent` with `@ForyField(ref=true)` | -| Python | `parent: Node` | `parent: Node = pyfory.field(ref=True)` | -| Go | `Parent Node` | `Parent *Node` with `fory:"ref"` | -| Rust | `parent: Node` | `parent: Arc` | -| C++ | `Node parent` | `std::shared_ptr parent` | - -Rust uses `Arc` by default; use `ref(thread_safe=false)` or `ref(weak=true)` -to customize pointer types. For protobuf option syntax, see -[Protocol Buffers IDL Support](protobuf-idl.md#field-level-options). +当运行时全局 ref tracking 开启时,字段级 `ref` 才会生效。 #### `list` -Marks the field as a list/array: +列表字段(`repeated` 为等价别名): ```protobuf -message Document { +message Group { list tags = 1; - list authors = 2; } ``` -**Generated Code:** - -| Language | Type | -| -------- | -------------------------- | -| Java | `List` | -| Python | `List[str]` | -| Go | `[]string` | -| Rust | `Vec` | -| C++ | `std::vector` | +### 组合修饰符 -### Combining Modifiers - -Modifiers can be combined: - -```fdl -message Example { - optional list tags = 1; // Nullable list - list aliases = 2; // Elements may be null - ref list nodes = 3; // Collection tracked as a reference - list children = 4; // Elements tracked as references - optional ref User owner = 5; // Nullable tracked reference -} -``` - -Modifiers before `list` apply to the field/collection. Modifiers after `list` -apply to elements. `repeated` is accepted as an alias for `list`. - -**List modifier mapping:** - -| Fory IDL | Java | Python | Go | Rust | C++ | -| ----------------------- | ---------------------------------------------- | --------------------------------------- | ----------------------- | --------------------- | ----------------------------------------- | -| `optional list` | `List` + `@ForyField(nullable = true)` | `Optional[List[str]]` | `[]string` + `nullable` | `Option>` | `std::optional>` | -| `list` | `List` (nullable elements) | `List[Optional[str]]` | `[]*string` | `Vec>` | `std::vector>` | -| `ref list` | `List` + `@ForyField(ref = true)` | `List[User]` + `pyfory.field(ref=True)` | `[]User` + `ref` | `Arc>` | `std::shared_ptr>` | -| `list` | `List` | `List[User]` | `[]*User` + `ref=false` | `Vec>` | `std::vector>` | - -Use `ref(thread_safe=false)` in Fory IDL (or `[(fory).thread_safe_pointer = false]` in protobuf) -to generate `Rc` instead of `Arc` in Rust. - -## Field Numbers - -Each field must have a unique positive integer identifier: +可组合使用: ```protobuf -message Example { - string first = 1; - string second = 2; - string third = 3; +message Graph { + optional ref Node root = 1; + list nodes = 2; } ``` -**Rules and best practices:** +## 字段号 -- Numbers must be unique within a message. -- Numbers must be positive integers. -- Gaps are allowed and are useful when fields are removed. -- Prefer sequential numbering from `1`. -- Never reuse a removed field number for a different field. +字段号规则: -## Type System +- 同一 message 内必须唯一 +- 必须为正整数 +- 不应复用已删除字段号(建议使用 `reserved`) +- 建议预留编号区间以便演进 -Fory IDL provides a cross-language type system for primitives, named types, and -collections. Field modifiers (`optional`, `list`, `ref`) control nullability, -collection behavior, and reference tracking (see -[Field Modifiers](#field-modifiers)). +## Type System {#type-system} + +Fory IDL 类型系统包括基础类型、命名类型和集合类型。 ### Primitive Types -| Type | Description | Size | -| --------------- | ----------------------------------------- | -------- | -| `bool` | Boolean value | 1 byte | -| `int8` | Signed 8-bit integer | 1 byte | -| `int16` | Signed 16-bit integer | 2 bytes | -| `int32` | Signed 32-bit integer (varint encoding) | 4 bytes | -| `int64` | Signed 64-bit integer (varint encoding) | 8 bytes | -| `uint8` | Unsigned 8-bit integer | 1 byte | -| `uint16` | Unsigned 16-bit integer | 2 bytes | -| `uint32` | Unsigned 32-bit integer (varint encoding) | 4 bytes | -| `uint64` | Unsigned 64-bit integer (varint encoding) | 8 bytes | -| `fixed_int32` | Signed 32-bit integer (fixed encoding) | 4 bytes | -| `fixed_int64` | Signed 64-bit integer (fixed encoding) | 8 bytes | -| `fixed_uint32` | Unsigned 32-bit integer (fixed encoding) | 4 bytes | -| `fixed_uint64` | Unsigned 64-bit integer (fixed encoding) | 8 bytes | -| `tagged_int64` | Signed 64-bit integer (tagged encoding) | 8 bytes | -| `tagged_uint64` | Unsigned 64-bit integer (tagged encoding) | 8 bytes | -| `float32` | 32-bit floating point | 4 bytes | -| `float64` | 64-bit floating point | 8 bytes | -| `string` | UTF-8 string | Variable | -| `bytes` | Binary data | Variable | -| `date` | Calendar date | Variable | -| `timestamp` | Date and time with timezone | Variable | -| `duration` | Duration | Variable | -| `decimal` | Decimal value | Variable | -| `any` | Dynamic value (runtime type) | Variable | +| 类型族 | 示例 | +| -------- | --------------------------------- | +| 布尔 | `bool` | +| 整数 | `int8/int16/int32/int64`、`uint*` | +| 浮点 | `float32`、`float64` | +| 字符串 | `string` | +| 字节数组 | `bytes` | +| 时间 | `date`、`timestamp`、`duration` | +| 动态类型 | `any` | #### Boolean -| Language | Type | Notes | -| -------- | --------------------- | ------------------ | -| Java | `boolean` / `Boolean` | Primitive or boxed | -| Python | `bool` | | -| Go | `bool` | | -| Rust | `bool` | | -| C++ | `bool` | | +`bool` 表示布尔值。 #### Integer Types -Fory IDL provides fixed-width signed integers (varint encoding for 32/64-bit by default): - -| Fory IDL Type | Size | Range | -| ------------- | ------ | ----------------- | -| `int8` | 8-bit | -128 to 127 | -| `int16` | 16-bit | -32,768 to 32,767 | -| `int32` | 32-bit | -2^31 to 2^31 - 1 | -| `int64` | 64-bit | -2^63 to 2^63 - 1 | - -**Language Mapping (Signed):** - -| Fory IDL | Java | Python | Go | Rust | C++ | -| -------- | ------- | -------------- | ------- | ----- | --------- | -| `int8` | `byte` | `pyfory.int8` | `int8` | `i8` | `int8_t` | -| `int16` | `short` | `pyfory.int16` | `int16` | `i16` | `int16_t` | -| `int32` | `int` | `pyfory.int32` | `int32` | `i32` | `int32_t` | -| `int64` | `long` | `pyfory.int64` | `int64` | `i64` | `int64_t` | - -Fory IDL provides fixed-width unsigned integers (varint encoding for 32/64-bit by default): - -| Fory IDL | Size | Range | -| -------- | ------ | ------------- | -| `uint8` | 8-bit | 0 to 255 | -| `uint16` | 16-bit | 0 to 65,535 | -| `uint32` | 32-bit | 0 to 2^32 - 1 | -| `uint64` | 64-bit | 0 to 2^64 - 1 | - -**Language Mapping (Unsigned):** - -| Fory IDL | Java | Python | Go | Rust | C++ | -| -------- | ------- | --------------- | -------- | ----- | ---------- | -| `uint8` | `short` | `pyfory.uint8` | `uint8` | `u8` | `uint8_t` | -| `uint16` | `int` | `pyfory.uint16` | `uint16` | `u16` | `uint16_t` | -| `uint32` | `long` | `pyfory.uint32` | `uint32` | `u32` | `uint32_t` | -| `uint64` | `long` | `pyfory.uint64` | `uint64` | `u64` | `uint64_t` | +支持有符号/无符号与不同位宽。跨语言场景建议明确编码策略并保持字段语义稳定。 #### Integer Encoding Variants -For 32/64-bit integers, Fory IDL uses varint encoding by default. Use explicit types when -you need fixed-width or tagged encoding: +常见编码: -| Fory IDL Type | Encoding | Notes | -| --------------- | -------- | ------------------------ | -| `fixed_int32` | fixed | Signed 32-bit | -| `fixed_int64` | fixed | Signed 64-bit | -| `fixed_uint32` | fixed | Unsigned 32-bit | -| `fixed_uint64` | fixed | Unsigned 64-bit | -| `tagged_int64` | tagged | Signed 64-bit (hybrid) | -| `tagged_uint64` | tagged | Unsigned 64-bit (hybrid) | +- `varint`:小值更省空间 +- `fixed`:固定长度,性能稳定 +- `tagged`:混合编码(特定类型可用) #### Floating-Point Types -| Fory IDL Type | Size | Precision | -| ------------- | ------ | ------------- | -| `float32` | 32-bit | ~7 digits | -| `float64` | 64-bit | ~15-16 digits | - -**Language Mapping:** - -| Fory IDL | Java | Python | Go | Rust | C++ | -| --------- | -------- | ---------------- | --------- | ----- | -------- | -| `float32` | `float` | `pyfory.float32` | `float32` | `f32` | `float` | -| `float64` | `double` | `pyfory.float64` | `float64` | `f64` | `double` | +- `float32` +- `float64` #### String Type -| Language | Type | Notes | -| -------- | ------------- | --------------------- | -| Java | `String` | Immutable | -| Python | `str` | | -| Go | `string` | Immutable | -| Rust | `String` | Owned, heap-allocated | -| C++ | `std::string` | | +`string` 使用 UTF-8 文本语义。 #### Bytes Type -| Language | Type | Notes | -| -------- | ---------------------- | --------- | -| Java | `byte[]` | | -| Python | `bytes` | Immutable | -| Go | `[]byte` | | -| Rust | `Vec` | | -| C++ | `std::vector` | | +`bytes` 用于原始二进制载荷。 #### Temporal Types ##### Date -| Language | Type | Notes | -| -------- | --------------------------- | ----------------------- | -| Java | `java.time.LocalDate` | | -| Python | `datetime.date` | | -| Go | `time.Time` | Time portion ignored | -| Rust | `chrono::NaiveDate` | Requires `chrono` crate | -| C++ | `fory::serialization::Date` | | +`date` 表示日期(不含时区时间部分)。 ##### Timestamp -| Language | Type | Notes | -| -------- | -------------------------------- | ----------------------- | -| Java | `java.time.Instant` | UTC-based | -| Python | `datetime.datetime` | | -| Go | `time.Time` | | -| Rust | `chrono::NaiveDateTime` | Requires `chrono` crate | -| C++ | `fory::serialization::Timestamp` | | +`timestamp` 表示时间点(跨语言应统一时间语义与精度预期)。 #### Any -| Language | Type | Notes | -| -------- | -------------- | -------------------- | -| Java | `Object` | Runtime type written | -| Python | `Any` | Runtime type written | -| Go | `any` | Runtime type written | -| Rust | `Box` | Runtime type written | -| C++ | `std::any` | Runtime type written | - -**Example:** - -```protobuf -enum EventType [id=120] { - CREATED = 0; - DELETED = 1; -} - -message UserCreated [id=121] { - string user_id = 1; -} - -message Envelope [id=122] { - EventType type = 1; - any payload = 2; -} -``` - -**Generated Code (`Envelope.payload`):** - -| Language | Generated Field Type | -| -------- | ----------------------- | -| Java | `Object payload` | -| Python | `payload: Any` | -| Go | `Payload any` | -| Rust | `payload: Box` | -| C++ | `std::any payload` | - -**Notes:** - -- `any` always writes a null flag (same as `nullable`) because values may be empty. -- Allowed runtime values are limited to `bool`, `string`, `enum`, `message`, and `union`. - Other primitives (numeric, bytes, date/time) and list/map are not supported; wrap them in a - message or use explicit fields instead. -- `ref` is not allowed on `any` fields (including list/map values). Wrap `any` in a message - if you need reference tracking. -- The runtime type must be registered in the target language schema/IDL registration; unknown - types fail to deserialize. +`any` 允许存储动态类型值。使用 `any` 时建议配合清晰的业务约束,避免滥用导致模型不稳定。 ### Named Types -Reference other messages, enums, or unions by name: +命名类型包括: -```protobuf -enum Status { ... } -message User { ... } +- `enum` +- `message` +- `union` -message Order { - User customer = 1; // Reference to User message - Status status = 2; // Reference to Status enum -} -``` +支持跨文件 import 和限定名引用。 ### Collection Types #### List (`list`) -Use the `list<...>` type for list fields. `repeated` is accepted as an alias. See [Field Modifiers](#field-modifiers) for -modifier combinations and language mapping. +```protobuf +list +``` -Nested collection types are not supported. Use a message wrapper if you need -`list>`, `list>`, or `map<..., list<...>>`. +等价别名:`repeated T`。 #### Map -Maps with typed keys and values: - ```protobuf -message Config { - map properties = 1; - map counts = 2; - map users = 3; -} +map ``` -**Language Mapping:** - -| Fory IDL | Java | Python | Go | Rust | C++ | -| -------------------- | ---------------------- | ----------------- | ------------------ | ----------------------- | -------------------------------- | -| `map` | `Map` | `Dict[str, int]` | `map[string]int32` | `HashMap` | `std::map` | -| `map` | `Map` | `Dict[str, User]` | `map[string]User` | `HashMap` | `std::map` | - -**Key Type Restrictions:** +约束: -- `string` (most common) -- Integer types (`int8`, `int16`, `int32`, `int64`) -- `bool` - -Avoid using messages or complex types as keys. +- `K` 一般应为可稳定比较的标量类型 +- `V` 可为任意支持类型 ### Type Compatibility Matrix -This matrix shows which type conversions are safe across languages: - -| From -> To | bool | int8 | int16 | int32 | int64 | float32 | float64 | string | -| ---------- | ---- | ---- | ----- | ----- | ----- | ------- | ------- | ------ | -| bool | Y | Y | Y | Y | Y | - | - | - | -| int8 | - | Y | Y | Y | Y | Y | Y | - | -| int16 | - | - | Y | Y | Y | Y | Y | - | -| int32 | - | - | - | Y | Y | - | Y | - | -| int64 | - | - | - | - | Y | - | - | - | -| float32 | - | - | - | - | - | Y | Y | - | -| float64 | - | - | - | - | - | - | Y | - | -| string | - | - | - | - | - | - | - | Y | +跨语言建议: -Y = Safe conversion, - = Not recommended +- 使用各语言都稳定支持的公共子集 +- 尽量避免平台相关宽度/语义差异 +- 对整数编码与可空语义显式声明 ### Best Practices -- Use `int32` as the default for most integers; use `int64` for large values. -- Use `string` for text data (UTF-8) and `bytes` for binary data. -- Use `optional` only when the field may legitimately be absent. -- Use `ref` only when needed for shared or circular references. -- Prefer `list` for ordered sequences and `map` for key-value lookups. +1. 优先使用显式字段号与稳定命名 +2. 需要可空就显式 `optional` +3. 存在共享/循环关系时使用 `ref` +4. 降低 `any` 使用范围,优先强类型建模 +5. 预留字段号与枚举值区间 ## Type IDs -Type IDs enable efficient cross-language serialization and are used for -messages, unions, and enums. When `enable_auto_type_id = true` (default) and -`id` is omitted, the compiler auto-generates one using -`MurmurHash3(utf8(package.type_name))` (32-bit) and annotates it in generated -code. When `enable_auto_type_id = false`, types without explicit IDs are -registered by namespace and name instead. Collisions are detected at -compile-time across the current file and all imports; when a collision occurs, -the compiler raises an error and asks for an explicit `id` or an `alias`. - -```protobuf -enum Color [id=100] { ... } -message User [id=101] { ... } -union Event [id=102] { ... } -``` - -Enum type IDs remain optional; if omitted they are auto-generated using the same -hash when `enable_auto_type_id = true`. +类型 ID 用于跨语言快速注册与解码匹配。 -### With Explicit Type ID +### 显式类型 ID ```protobuf -message User [id=101] { ... } -message User [id=101, deprecated=true] { ... } // Multiple options +message User [id=100] { + string name = 1; +} ``` -### Without Explicit Type ID +### 无显式类型 ID -```protobuf -message Config { ... } // Auto-generated when enable_auto_type_id = true -``` +未显式声明时可: -You can set `[alias="..."]` to change the hash source without renaming the type. +- 自动生成数值 ID(默认配置) +- 禁用自动 ID,改用 namespace/type-name 注册 -### Practical Notes +### 实践说明 -- If a type omits `id` and `enable_auto_type_id = true`, Fory generates an ID - with `MurmurHash3(utf8(package.type_name))` (32-bit). -- Package alias and type alias change the hash input and can be used to resolve - hash collisions without renaming public types. -- Manual IDs in the small varint range (`0-127`) are compact on the wire; auto - IDs are typically larger and usually consume 4-5 bytes. +- 类型 ID 在协议层面应视为稳定标识 +- 一经发布,不建议更改 +- 建议按域规划 ID 段(如 100-199 用户域) -### ID Assignment Strategy +### ID 分配策略 -```protobuf -// Enums: 100-199 -enum Status [id=100] { ... } -enum Priority [id=101] { ... } +- 核心高频模型优先分配固定 ID +- 团队统一管理 ID 区间与分配规范 +- 在 CI 中增加 ID 冲突检查 -// User domain: 200-299 -message User [id=200] { ... } -message UserProfile [id=201] { ... } +## 完整示例 -// Order domain: 300-399 -message Order [id=300] { ... } -message OrderItem [id=301] { ... } -``` +```protobuf +package demo.order; -## Complete Example +option java_package = "com.example.demo.order"; +option go_package = "github.com/example/demo/gen/order;order"; -```protobuf -// E-commerce domain model -package com.shop.models; - -// Enums with type IDs -enum OrderStatus [id=100] { - PENDING = 0; - CONFIRMED = 1; - SHIPPED = 2; - DELIVERED = 3; - CANCELLED = 4; -} +import "demo/common.fdl"; -enum PaymentMethod [id=101] { - CREDIT_CARD = 0; - DEBIT_CARD = 1; - PAYPAL = 2; - BANK_TRANSFER = 3; +enum Status [id=200] { + UNKNOWN = 0; + CREATED = 1; + PAID = 2; + SHIPPED = 3; } -// Messages with type IDs -message Address [id=200] { - string street = 1; - string city = 2; - string state = 3; - string country = 4; - string postal_code = 5; +message Item [id=201] { + string sku = 1; + int32 quantity = 2; } -message Customer [id=201] { +message User [id=202] { string id = 1; string name = 2; optional string email = 3; - optional string phone = 4; - optional Address billing_address = 5; - optional Address shipping_address = 6; } -message Product [id=202] { - string sku = 1; - string name = 2; - string description = 3; - float64 price = 4; - int32 stock = 5; - list categories = 6; - map attributes = 7; +union Animal [id=203] { + Dog dog = 1; + Cat cat = 2; } -message OrderItem [id=203] { - ref Product product = 1; // Track reference to avoid duplication - int32 quantity = 2; - float64 unit_price = 3; +message Dog [id=204] { + string name = 1; } -message Order [id=204] { - string id = 1; - ref Customer customer = 2; - list items = 3; - OrderStatus status = 4; - PaymentMethod payment_method = 5; - float64 total = 6; - optional string notes = 7; - timestamp created_at = 8; - optional timestamp shipped_at = 9; +message Cat [id=205] { + string name = 1; } -// Config without explicit type ID (auto-generated when enable_auto_type_id = true) -message ShopConfig { - string store_name = 1; - string currency = 2; - float64 tax_rate = 3; - list supported_countries = 4; +message Order [id=206] { + string id = 1; + ref User buyer = 2; + list items = 3; + Status status = 4; + map metadata = 5; + optional Animal pet = 6; } ``` -For protobuf-specific extension options and `(fory).` syntax, see -[Protocol Buffers IDL Support](protobuf-idl.md#fory-extension-options-protobuf). +## 语法摘要 -## Grammar Summary +以下为简化文法(便于快速查阅,具体以编译器实现为准): +```ebnf +file = [packageDecl] {optionDecl} {importDecl} {typeDecl} ; + +packageDecl = "package" qualifiedName ["alias" identifier] ";" ; +optionDecl = "option" identifier "=" optionValue ";" ; +importDecl = "import" stringLiteral ";" ; + +typeDecl = enumDecl | messageDecl | unionDecl ; + +enumDecl = "enum" identifier [typeOptions] "{" {enumField | reservedDecl} "}" ; +enumField = identifier "=" intLiteral ";" ; + +messageDecl = "message" identifier [typeOptions] "{" {fieldDecl | nestedTypeDecl | reservedDecl} "}" ; +unionDecl = "union" identifier [typeOptions] "{" {unionCaseDecl} "}" ; + +fieldDecl = [fieldModifier] typeRef identifier "=" intLiteral [fieldOptions] ";" ; +unionCaseDecl = typeRef identifier "=" intLiteral [fieldOptions] ";" ; + +fieldModifier = "optional" | "ref" | "list" ; + +typeRef = primitiveType | qualifiedName | listType | mapType ; +listType = "list" "<" typeRef ">" ; +mapType = "map" "<" typeRef "," typeRef ">" ; + +typeOptions = "[" optionPair {"," optionPair} "]" ; +fieldOptions = "[" optionPair {"," optionPair} "]" ; +optionPair = identifier "=" optionValue ; + +reservedDecl = "reserved" reservedItem {"," reservedItem} ";" ; +reservedItem = intLiteral | intLiteral "to" intLiteral | stringLiteral ; ``` -file := [package_decl] file_option* import_decl* type_def* - -package_decl := 'package' package_name ['alias' package_name] ';' -package_name := IDENTIFIER ('.' IDENTIFIER)* - -file_option := 'option' option_name '=' option_value ';' -option_name := IDENTIFIER - -import_decl := 'import' STRING ';' - -type_def := enum_def | message_def | union_def - -enum_def := 'enum' IDENTIFIER [type_options] '{' enum_body '}' -enum_body := (reserved_stmt | enum_value)* -enum_value := IDENTIFIER '=' INTEGER ';' - -message_def := 'message' IDENTIFIER [type_options] '{' message_body '}' -message_body := (reserved_stmt | nested_type | field_def)* -nested_type := enum_def | message_def | union_def -field_def := [modifiers] field_type IDENTIFIER '=' INTEGER [field_options] ';' - -union_def := 'union' IDENTIFIER [type_options] '{' union_field* '}' -union_field := ['repeated'] field_type IDENTIFIER '=' INTEGER [field_options] ';' -option_value := 'true' | 'false' | IDENTIFIER | INTEGER | STRING - -reserved_stmt := 'reserved' reserved_items ';' -reserved_items := reserved_item (',' reserved_item)* -reserved_item := INTEGER | INTEGER 'to' INTEGER | INTEGER 'to' 'max' | STRING - -modifiers := { 'optional' | 'ref' | 'repeated' } - -field_type := primitive_type | named_type | list_type | map_type -primitive_type := 'bool' - | 'int8' | 'int16' | 'int32' | 'int64' - | 'uint8' | 'uint16' | 'uint32' | 'uint64' - | 'fixed_int32' | 'fixed_int64' | 'fixed_uint32' | 'fixed_uint64' - | 'tagged_int64' | 'tagged_uint64' - | 'float32' | 'float64' - | 'string' | 'bytes' - | 'date' | 'timestamp' | 'duration' | 'decimal' - | 'any' -named_type := qualified_name -qualified_name := IDENTIFIER ('.' IDENTIFIER)* // e.g., Parent.Child -list_type := 'list' '<' { 'optional' | 'ref' } field_type '>' -map_type := 'map' '<' field_type ',' field_type '>' - -type_options := '[' type_option (',' type_option)* ']' -type_option := IDENTIFIER '=' option_value // e.g., id=100, deprecated=true -field_options := '[' field_option (',' field_option)* ']' -field_option := IDENTIFIER '=' option_value // e.g., deprecated=true, ref=true - -STRING := '"' [^"\n]* '"' | "'" [^'\n]* "'" -IDENTIFIER := [a-zA-Z_][a-zA-Z0-9_]* -INTEGER := '-'? [0-9]+ -``` + +实现建议:如需严谨验证,请以编译器语法解析器和测试用例为准。 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/cpp/field-configuration.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/cpp/field-configuration.md index 0c18e125ce..4dd404c290 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/cpp/field-configuration.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/cpp/field-configuration.md @@ -19,25 +19,22 @@ license: | limitations under the License. --- -> 中文导读:本页介绍字段级序列化配置,包括字段 ID、可空控制、引用跟踪、忽略字段与动态类型控制等。 -> 建议在跨语言和兼容模式场景中优先显式配置字段 ID,并在需要时开启 ref/nullable 以保证行为一致。 - -本页说明如何配置序列化的字段级元信息。 +本页说明如何在 C++ 中配置序列化字段级元信息。 ## 概述 -Apache Fory™ provides two ways to specify field-level metadata at compile time: +Apache Fory™ 在编译期提供两种字段元信息配置方式: -1. **`fory::field<>` template** - Inline metadata in struct definition -2. **`FORY_FIELD_TAGS` macro** - Non-invasive metadata added separately +1. **`fory::field<>` 模板**:在 struct 定义中内联声明元信息 +2. **`FORY_FIELD_TAGS` 宏**:在 struct 外部附加元信息(非侵入) -These enable: +这些机制可用于: -- **Tag IDs**: Assign compact numeric IDs for schema evolution -- **Nullability**: Mark pointer fields as nullable -- **Reference Tracking**: Enable reference tracking for shared pointers +- **Tag ID**:为 schema 演进分配紧凑数值 ID +- **可空控制**:将指针字段标记为可空 +- **引用跟踪**:为共享指针启用引用跟踪 -## fory::field 模板 +## `fory::field` 模板 ```cpp template @@ -46,11 +43,11 @@ class field; ### 模板参数 -| Parameter | Description | -| --------- | ------------------------------------------------ | -| `T` | The underlying field type | -| `Id` | Field tag ID (int16_t) for compact serialization | -| `Options` | Optional tags: `fory::nullable`, `fory::ref` | +| 参数 | 说明 | +| --------- | ------------------------------------------ | +| `T` | 底层字段类型 | +| `Id` | 字段 tag ID(`int16_t`),用于紧凑序列化 | +| `Options` | 可选标签:`fory::nullable`、`fory::ref` 等 | ### 基本用法 @@ -67,7 +64,7 @@ struct Person { FORY_STRUCT(Person, name, age, nickname); ``` -The `fory::field<>` wrapper is transparent - you can use it like the underlying type: +`fory::field<>` 是透明包装,可像底层类型一样使用: ```cpp Person person; @@ -79,9 +76,9 @@ int a = person.age.get(); // Explicit get() ## 标签类型 -### fory::nullable +### `fory::nullable` -Marks a smart pointer field as nullable (can be `nullptr`): +将智能指针字段标记为可空(可为 `nullptr`): ```cpp struct Node { @@ -91,9 +88,9 @@ struct Node { FORY_STRUCT(Node, name, next); ``` -**Valid for:** `std::shared_ptr`, `std::unique_ptr` +**适用类型:** `std::shared_ptr`、`std::unique_ptr` -**Note:** For nullable primitives or strings, use `std::optional` instead: +**说明:** 对原生值类型或字符串的可空语义,请使用 `std::optional`: ```cpp // Correct: use std::optional for nullable primitives @@ -103,19 +100,19 @@ fory::field, 0> optional_value; // fory::field value; // Compile error! ``` -### fory::not_null +### `fory::not_null` -Explicitly marks a pointer field as non-nullable. This is the default for smart pointers, but can be used for documentation: +显式声明指针字段不可空。虽然这是智能指针的默认行为,但可用于增强可读性: ```cpp fory::field, 0, fory::not_null> data; // Must not be nullptr ``` -**Valid for:** `std::shared_ptr`, `std::unique_ptr` +**适用类型:** `std::shared_ptr`、`std::unique_ptr` -### fory::ref +### `fory::ref` -Enables reference tracking for shared pointer fields. When multiple fields reference the same object, it will be serialized once and shared: +为共享指针字段启用引用跟踪。多个字段引用同一对象时,仅序列化一次并保持共享关系: ```cpp struct Graph { @@ -126,27 +123,27 @@ struct Graph { FORY_STRUCT(Graph, name, left, right); ``` -**Valid for:** `std::shared_ptr` only (requires shared ownership) +**适用类型:** 仅 `std::shared_ptr`(需要共享所有权) -### Combining Tags +### 组合标签 -Multiple tags can be combined for shared pointers: +共享指针可组合多个标签: ```cpp // Nullable + ref tracking fory::field, 0, fory::nullable, fory::ref> link; ``` -## Type Rules +## 类型规则 -| Type | Allowed Options | Nullability | -| -------------------- | ----------------- | ---------------------------------- | -| Primitives, strings | None | Use `std::optional` if nullable | -| `std::optional` | None | Inherently nullable | -| `std::shared_ptr` | `nullable`, `ref` | Non-null by default | -| `std::unique_ptr` | `nullable` | Non-null by default | +| 类型 | 可用选项 | 可空语义 | +| -------------------- | ----------------- | --------------------------------- | +| 原生类型、字符串 | 无 | 若需可空请使用 `std::optional` | +| `std::optional` | 无 | 天然可空 | +| `std::shared_ptr` | `nullable`、`ref` | 默认不可空 | +| `std::unique_ptr` | `nullable` | 默认不可空 | -## Complete Example +## 完整示例 ```cpp #include "fory/serialization/fory.h" @@ -191,9 +188,9 @@ int main() { } ``` -## Compile-Time Validation +## 编译期校验 -Invalid configurations are caught at compile time: +非法配置会在编译期报错: ```cpp // Error: nullable and not_null are mutually exclusive @@ -209,9 +206,9 @@ fory::field, 0, fory::ref> bad3; fory::field, 0, fory::nullable> bad4; ``` -## Backwards Compatibility +## 向后兼容 -Existing structs without `fory::field<>` wrappers continue to work: +未使用 `fory::field<>` 包装的旧 struct 仍可正常工作: ```cpp // Old style - still works @@ -229,15 +226,15 @@ struct ModernPerson { FORY_STRUCT(ModernPerson, name, age); ``` -## FORY_FIELD_TAGS Macro +## `FORY_FIELD_TAGS` 宏 -The `FORY_FIELD_TAGS` macro provides a non-invasive way to add field metadata without modifying struct definitions. This is useful for: +`FORY_FIELD_TAGS` 提供了一种非侵入式方案:无需修改 struct 定义即可附加字段元信息。适用场景: -- **Third-party types**: Add metadata to types you don't own -- **Clean structs**: Keep struct definitions as pure C++ -- **Isolated dependencies**: Confine Fory headers to serialization config files +- **第三方类型**:为非自有类型添加元信息 +- **纯净结构定义**:保持 struct 仅包含标准 C++ 类型 +- **依赖隔离**:将 Fory 头文件限制在序列化配置文件中 -### Usage +### 用法 ```cpp // user_types.h - NO fory headers needed! @@ -268,33 +265,33 @@ FORY_FIELD_TAGS(Document, ) ``` -### FORY_FIELD_TAGS Options +### `FORY_FIELD_TAGS` 选项 -| Field Type | Valid Combinations | +| 字段类型 | 合法组合 | | -------------------- | ---------------------------------------------------------------------------------------- | -| Primitives, strings | `(field, id)` only | -| `std::optional` | `(field, id)` only | -| `std::shared_ptr` | `(field, id)`, `(field, id, nullable)`, `(field, id, ref)`, `(field, id, nullable, ref)` | -| `std::unique_ptr` | `(field, id)`, `(field, id, nullable)` | +| 原生类型、字符串 | 仅 `(field, id)` | +| `std::optional` | 仅 `(field, id)` | +| `std::shared_ptr` | `(field, id)`、`(field, id, nullable)`、`(field, id, ref)`、`(field, id, nullable, ref)` | +| `std::unique_ptr` | `(field, id)`、`(field, id, nullable)` | -### API Comparison +### API 对比 -| Aspect | `fory::field<>` Wrapper | `FORY_FIELD_TAGS` Macro | -| ----------------------- | ------------------------ | ----------------------- | -| **Struct definition** | Modified (wrapped types) | Unchanged (pure C++) | -| **IDE support** | Template noise | Excellent (clean types) | -| **Third-party classes** | Not supported | Supported | -| **Header dependencies** | Required everywhere | Isolated to config | -| **Migration effort** | High (change all fields) | Low (add one macro) | +| 维度 | `fory::field<>` 包装 | `FORY_FIELD_TAGS` 宏 | +| -------------- | ------------------------ | ---------------------- | +| **结构定义** | 需要改动(包装字段类型) | 无需改动(保持纯 C++) | +| **IDE 体验** | 有模板噪音 | 更清晰(原生字段类型) | +| **第三方类型** | 不支持 | 支持 | +| **头文件依赖** | 各处都需要 | 可集中在配置文件 | +| **迁移成本** | 高(修改全部字段) | 低(新增一个宏) | -## FORY_FIELD_CONFIG Macro +## `FORY_FIELD_CONFIG` 宏 -The `FORY_FIELD_CONFIG` macro is the most powerful and flexible way to configure field-level serialization. It provides: +`FORY_FIELD_CONFIG` 是更强、更灵活的字段配置方式,提供: -- **Builder pattern API**: Fluent, chainable configuration with `F(id).option1().option2()` -- **Encoding control**: Specify how unsigned integers are encoded (varint, fixed, tagged) -- **Compile-time verification**: Field names are verified against member pointers -- **Cross-language compatibility**: Configure encoding to match other languages (Java, Rust, etc.) +- **Builder 风格 API**:链式配置 `F(id).option1().option2()` +- **编码控制**:指定无符号整数编码(varint、fixed、tagged) +- **编译期校验**:通过成员指针校验字段名 +- **跨语言兼容**:按 Java、Rust 等语言期望配置编码 ### 基本语法 @@ -308,9 +305,9 @@ FORY_FIELD_CONFIG(StructType, ); ``` -### The F() Builder +### `F()` Builder -The `fory::F(id)` factory creates a `FieldMeta` object that supports method chaining: +`fory::F(id)` 工厂函数会创建支持链式调用的 `FieldMeta` 对象: ```cpp fory::F(0) // Create with field ID 0 @@ -323,7 +320,7 @@ fory::F(0) // Create with field ID 0 .compress(false) // Disable compression ``` -**Tip:** To use `F()` without the `fory::` prefix, add a using declaration: +**提示:** 若希望省略 `fory::` 前缀,可添加 `using` 声明: ```cpp using fory::F; @@ -334,19 +331,19 @@ FORY_FIELD_CONFIG(MyStruct, ); ``` -### Encoding Options for Unsigned Integers +### 无符号整数编码选项 -For `uint32_t` and `uint64_t` fields, you can specify the wire encoding: +对于 `uint32_t` 与 `uint64_t` 字段,可显式指定线格式编码: -| Method | Type ID | Description | Use Case | -| ----------- | ------------- | ---------------------------------------------- | ------------------------------------- | -| `.varint()` | VAR_UINT32/64 | Variable-length encoding (1-5 or 1-10 bytes) | Values typically small | -| `.fixed()` | UINT32/64 | Fixed-size encoding (always 4 or 8 bytes) | Values uniformly distributed | -| `.tagged()` | TAGGED_UINT64 | Tagged hybrid encoding with size hint (uint64) | Mixed small and large values (uint64) | +| 方法 | Type ID | 说明 | 适用场景 | +| ----------- | ------------- | --------------------------------- | ------------------------ | +| `.varint()` | VAR_UINT32/64 | 变长编码(1-5 或 1-10 字节) | 数值通常较小 | +| `.fixed()` | UINT32/64 | 定长编码(固定 4 或 8 字节) | 数值分布较均匀 | +| `.tagged()` | TAGGED_UINT64 | 带大小提示的混合编码(仅 uint64) | 小值与大值混合(uint64) | -**Note:** `uint8_t` and `uint16_t` always use fixed encoding (UINT8, UINT16). +**说明:** `uint8_t` 与 `uint16_t` 始终使用定长编码(UINT8、UINT16)。 -### Complete Example +### 完整示例 ```cpp #include "fory/serialization/fory.h" @@ -411,11 +408,11 @@ int main() { } ``` -### Cross-Language Compatibility +### 跨语言兼容 -When serializing data to be read by other languages, use `FORY_FIELD_CONFIG` to match their encoding expectations: +当序列化数据会被其他语言读取时,建议通过 `FORY_FIELD_CONFIG` 显式匹配目标语言编码约定。 -**Java Compatibility:** +**Java 兼容示例:** ```cpp // Java uses these type IDs for unsigned integers: @@ -446,9 +443,9 @@ FORY_FIELD_CONFIG(JavaCompatible, ); ``` -### Schema Evolution with FORY_FIELD_CONFIG +### 使用 `FORY_FIELD_CONFIG` 做 Schema 演进 -In compatible mode, fields can have different nullability between sender and receiver: +在兼容模式下,发送端和接收端可以对字段使用不同可空策略: ```cpp // Version 1: All fields non-nullable @@ -476,32 +473,32 @@ FORY_FIELD_CONFIG(DataV2, ); ``` -### FORY_FIELD_CONFIG Options Reference - -| Method | Description | Valid For | -| ---------------- | ------------------------------------------- | -------------------------- | -| `.nullable()` | Mark field as nullable | Smart pointers, primitives | -| `.ref()` | Enable reference tracking | `std::shared_ptr` only | -| `.monomorphic()` | Mark pointer as always pointing to one type | Smart pointers | -| `.varint()` | Use variable-length encoding | `uint32_t`, `uint64_t` | -| `.fixed()` | Use fixed-size encoding | `uint32_t`, `uint64_t` | -| `.tagged()` | Use tagged hybrid encoding | `uint64_t` only | -| `.compress(v)` | Enable/disable field compression | All types | - -### Comparing Field Configuration Macros - -| Feature | `fory::field<>` | `FORY_FIELD_TAGS` | `FORY_FIELD_CONFIG` | -| ----------------------- | --------------------- | ----------------- | ------------------------- | -| **Struct modification** | Required (wrap types) | None | None | -| **Encoding control** | No | No | Yes (varint/fixed/tagged) | -| **Builder pattern** | No | No | Yes | -| **Compile-time verify** | Yes | Limited | Yes (member pointers) | -| **Cross-lang compat** | Limited | Limited | Full | -| **Recommended for** | Simple structs | Third-party types | Complex/xlang structs | - -## Related Topics - -- [Type Registration](type-registration.md) - Registering types with FORY_STRUCT -- [Schema Evolution](schema-evolution.md) - Using tag IDs for schema evolution -- [Configuration](configuration.md) - Enabling reference tracking globally -- [Cross-Language](cross-language.md) - Interoperability with Java, Rust, Python +### `FORY_FIELD_CONFIG` 选项速查 + +| 方法 | 说明 | 适用范围 | +| ---------------- | ------------------------ | ---------------------- | +| `.nullable()` | 将字段标记为可空 | 智能指针、可空值类型 | +| `.ref()` | 启用引用跟踪 | 仅 `std::shared_ptr` | +| `.monomorphic()` | 标记指针始终指向单一类型 | 智能指针 | +| `.varint()` | 变长编码 | `uint32_t`、`uint64_t` | +| `.fixed()` | 定长编码 | `uint32_t`、`uint64_t` | +| `.tagged()` | tagged 混合编码 | 仅 `uint64_t` | +| `.compress(v)` | 启用/禁用字段压缩 | 所有类型 | + +### 字段配置方案对比 + +| 特性 | `fory::field<>` | `FORY_FIELD_TAGS` | `FORY_FIELD_CONFIG` | +| ------------------- | ------------------ | ----------------- | ------------------------- | +| **需要修改 struct** | 是(包装字段类型) | 否 | 否 | +| **编码控制** | 否 | 否 | 是(varint/fixed/tagged) | +| **Builder 风格** | 否 | 否 | 是 | +| **编译期校验** | 是 | 有限 | 是(成员指针校验) | +| **跨语言兼容能力** | 有限 | 有限 | 完整 | +| **推荐场景** | 简单结构体 | 第三方类型 | 复杂/跨语言结构体 | + +## 相关主题 + +- [类型注册](type-registration.md) - 使用 FORY_STRUCT 注册类型 +- [Schema 演进](schema-evolution.md) - 基于 tag ID 的演进策略 +- [配置](configuration.md) - 全局启用引用跟踪等选项 +- [跨语言](cross-language.md) - 与 Java、Rust、Python 的互操作 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/cpp/schema-evolution.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/cpp/schema-evolution.md index 3f89d97aad..fd8c7bfcad 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/cpp/schema-evolution.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/cpp/schema-evolution.md @@ -85,7 +85,7 @@ Compatible 模式支持以下 schema 变更: | 添加新字段 | ✅ | 缺失字段使用默认值 | | 删除字段 | ✅ | 额外字段被跳过 | | 重排字段顺序 | ✅ | 按名称匹配字段,而非位置 | -| 更改可空性 | ✅ | `T` ↔ `std::optional` | +| 更改可空性 | ✅ | `T` ↔ `std::optional` | | 更改字段类型 | ❌ | 类型必须兼容 | | 重命名字段 | ❌ | 字段名必须匹配(区分大小写) | diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/go/configuration.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/go/configuration.md index ca1a0e0b24..770e5a1022 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/go/configuration.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/go/configuration.md @@ -33,12 +33,12 @@ f := fory.New() 默认设置: -| Option | Default | Description | -| ---------- | ------- | ------------------------------ | -| TrackRef | false | 关闭引用跟踪 | -| MaxDepth | 20 | 最大嵌套深度 | -| IsXlang | false | 关闭跨语言模式 | -| Compatible | false | 关闭 Schema 演进兼容模式 | +| Option | Default | Description | +| ---------- | ------- | ------------------------ | +| TrackRef | false | 关闭引用跟踪 | +| MaxDepth | 20 | 最大嵌套深度 | +| IsXlang | false | 关闭跨语言模式 | +| Compatible | false | 关闭 Schema 演进兼容模式 | ### 通过选项配置 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/go/index.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/go/index.md index 4e695875ac..a161c83606 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/go/index.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/go/index.md @@ -143,19 +143,19 @@ data, _ := f.Serialize(&User{ID: 1, Name: "Alice"}) ## 文档导航 -| 主题 | 说明 | -| -------------------------------------------- | -------------------------------------- | -| [配置](configuration.md) | 配置项与运行参数 | -| [基本序列化](basic-serialization.md) | 核心 API 与使用模式 | -| [类型注册](type-registration.md) | 序列化前的类型注册 | -| [支持类型](supported-types.md) | 完整类型支持说明 | -| [引用](references.md) | 循环引用与共享对象 | -| [Struct 标签](struct-tags.md) | 字段级配置 | -| [Schema 演进](schema-evolution.md) | 前向/后向兼容策略 | -| [跨语言](cross-language.md) | 多语言序列化 | -| [代码生成](codegen.md) | 实验性的 AOT 代码生成 | -| [线程安全](thread-safety.md) | 并发使用模式 | -| [故障排查](troubleshooting.md) | 常见问题与解决方案 | +| 主题 | 说明 | +| ------------------------------------ | --------------------- | +| [配置](configuration.md) | 配置项与运行参数 | +| [基本序列化](basic-serialization.md) | 核心 API 与使用模式 | +| [类型注册](type-registration.md) | 序列化前的类型注册 | +| [支持类型](supported-types.md) | 完整类型支持说明 | +| [引用](references.md) | 循环引用与共享对象 | +| [Struct 标签](struct-tags.md) | 字段级配置 | +| [Schema 演进](schema-evolution.md) | 前向/后向兼容策略 | +| [跨语言](cross-language.md) | 多语言序列化 | +| [代码生成](codegen.md) | 实验性的 AOT 代码生成 | +| [线程安全](thread-safety.md) | 并发使用模式 | +| [故障排查](troubleshooting.md) | 常见问题与解决方案 | ## 相关资源 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/go/struct-tags.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/go/struct-tags.md index 4579a1d744..a62b32770a 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/go/struct-tags.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/go/struct-tags.md @@ -19,14 +19,11 @@ license: | limitations under the License. --- -> 中文导读:本页介绍字段级序列化配置,包括字段 ID、可空控制、引用跟踪、忽略字段与动态类型控制等。 -> 建议在跨语言和兼容模式场景中优先显式配置字段 ID,并在需要时开启 ref/nullable 以保证行为一致。 - -Fory Go uses struct tags to customize field-level serialization behavior. This allows fine-grained control over how individual fields are serialized. +Fory Go 通过 struct tag 自定义字段级序列化行为,从而精细控制每个字段如何序列化。 ## 标签语法 -The general syntax for Fory struct tags: +Fory struct tag 的通用格式如下: ```go type MyStruct struct { @@ -34,13 +31,13 @@ type MyStruct struct { } ``` -Multiple options are separated by commas (`,`). +多个选项使用逗号(`,`)分隔。 ## 可用标签 ### 字段 ID -Use `id=N` to assign a numeric ID to a field for compact encoding: +使用 `id=N` 为字段分配数值 ID,以获得更紧凑编码: ```go type User struct { @@ -50,21 +47,21 @@ type User struct { } ``` -**Benefits**: +**收益:** -- Smaller serialized size (numeric IDs vs field names) -- Faster serialization/deserialization -- Required for optimal cross-language compatibility +- 序列化体积更小(数值 ID 替代字段名) +- 序列化/反序列化更快 +- 跨语言兼容场景下更推荐 -**Notes**: +**注意:** -- IDs must be unique within a struct -- IDs must be >= 0 -- If not specified, field name is used (larger payload) +- 同一 struct 内 ID 必须唯一 +- ID 必须 `>= 0` +- 未指定时使用字段名(payload 更大) ### 忽略字段 -Use `-` to exclude a field from serialization: +使用 `-` 将字段排除在序列化之外: ```go type User struct { @@ -74,11 +71,11 @@ type User struct { } ``` -The `Password` field will not be included in serialized output and will remain at its zero value after deserialization. +`Password` 不会进入序列化结果,反序列化后将保持该类型零值。 ### 可空控制 -Use `nullable` to control whether null flags are written for pointer fields: +使用 `nullable` 控制是否为指针字段写入 null 标记: ```go type Record struct { @@ -90,15 +87,15 @@ type Record struct { } ``` -**Notes**: +**注意:** -- Only applies to pointer, slice, and map fields -- When `nullable=false`, serializing a nil value will cause an error -- Default is `false` (no null flag written) +- 仅适用于指针、slice、map 字段 +- `nullable=false` 时,序列化 nil 会报错 +- 默认是 `false`(不写 null 标记) ### 引用跟踪 -Control per-field reference tracking for slices, maps, or pointer to struct fields: +可为 slice、map、或“指向 struct 的指针字段”设置字段级引用跟踪: ```go type Container struct { @@ -110,22 +107,22 @@ type Container struct { } ``` -**Notes**: +**注意:** -- Applies to slices, maps, and pointer to struct fields -- Pointer to primitive types (e.g., `*int`, `*string`) cannot use this tag -- Default is `ref=false` (no reference tracking) -- When global `WithTrackRef(false)` is set, field ref tags are ignored -- When global `WithTrackRef(true)` is set, use `ref=false` to disable for specific fields +- 适用于 slice、map 与“指向 struct 的指针字段” +- 指向原生类型的指针(如 `*int`、`*string`)不能使用该标签 +- 默认 `ref=false`(不开启引用跟踪) +- 全局 `WithTrackRef(false)` 时,字段级 ref 标签会被忽略 +- 全局 `WithTrackRef(true)` 时,可用 `ref=false` 对单字段禁用 -**Use cases**: +**适用场景:** -- Enable for fields that may be circular or shared -- Disable for fields that are always unique (optimization) +- 可能出现共享或循环引用的字段 +- 可明确唯一的字段可禁用(性能优化) -### Encoding +### 编码控制 -Use `encoding` to control how numeric fields are encoded: +使用 `encoding` 控制数值字段编码方式: ```go type Metrics struct { @@ -140,24 +137,24 @@ type Metrics struct { } ``` -**Supported encodings**: +**支持编码:** -| Type | Options | Default | +| 类型 | 可选值 | 默认值 | | -------- | --------------------------- | -------- | -| `int32` | `varint`, `fixed` | `varint` | -| `uint32` | `varint`, `fixed` | `varint` | -| `int64` | `varint`, `fixed`, `tagged` | `varint` | -| `uint64` | `varint`, `fixed`, `tagged` | `varint` | +| `int32` | `varint`、`fixed` | `varint` | +| `uint32` | `varint`、`fixed` | `varint` | +| `int64` | `varint`、`fixed`、`tagged` | `varint` | +| `uint64` | `varint`、`fixed`、`tagged` | `varint` | -**When to use**: +**何时使用:** -- `varint`: Best for values that are often small (default) -- `fixed`: Best for values that use full range (e.g., timestamps, hashes) -- `tagged`: When type information needs to be preserved +- `varint`:适合小值居多(默认) +- `fixed`:适合接近全值域分布(如时间戳、哈希) +- `tagged`:适合需保留类型信息的场景 -**Shorthand for int32/uint32**: +**int32/uint32 简写:** -Use `compress` as a convenience tag for int32/uint32 fields: +对 int32/uint32 字段可使用 `compress` 作为便捷标签: ```go type Data struct { @@ -166,9 +163,9 @@ type Data struct { } ``` -## Combining Tags +## 组合标签 -Multiple tags can be combined using comma separator: +多个标签可使用逗号组合: ```go type Document struct { @@ -178,9 +175,9 @@ type Document struct { } ``` -## Integration with Other Tags +## 与其他标签共存 -Fory tags coexist with other struct tags: +Fory 标签可与其他 struct tag 并存: ```go type User struct { @@ -190,11 +187,11 @@ type User struct { } ``` -Each tag namespace is independent. +各标签命名空间互不影响。 -## Field Visibility +## 字段可见性 -Only **exported fields** (starting with uppercase) are considered: +仅处理**导出字段**(首字母大写): ```go type User struct { @@ -204,26 +201,26 @@ type User struct { } ``` -Unexported fields are always ignored, regardless of tags. +未导出字段始终忽略,与是否配置 tag 无关。 -## Field Ordering +## 字段顺序 -Fields are serialized in a consistent order based on: +字段会按稳定顺序序列化,依据: -1. Field name (alphabetically in snake_case) -2. Field type +1. 字段名(snake_case 字典序) +2. 字段类型 -This ensures cross-language compatibility where field order matters. +这可保证跨语言场景下的字段顺序一致性。 -## Struct Hash +## Struct 哈希 -Fory computes a hash of struct fields for version checking: +Fory 会基于 struct 字段计算哈希用于版本校验: -- Hash includes field names and types -- Hash is written to serialized data -- Mismatch triggers `ErrKindHashMismatch` +- 哈希包含字段名与字段类型 +- 哈希会写入序列化数据 +- 不匹配会触发 `ErrKindHashMismatch` -Struct field changes affect the hash: +结构字段变更会影响哈希: ```go // These produce different hashes @@ -236,9 +233,9 @@ type V2 struct { } ``` -## Examples +## 示例 -### API Response Struct +### API 响应结构 ```go type APIResponse struct { @@ -249,7 +246,7 @@ type APIResponse struct { } ``` -### Caching with Shared References +### 带共享引用的缓存结构 ```go type CacheEntry struct { @@ -260,7 +257,7 @@ type CacheEntry struct { } ``` -### Document with Circular References +### 带循环引用的文档结构 ```go type Document struct { @@ -271,9 +268,9 @@ type Document struct { } ``` -## Tag Parsing Errors +## 标签解析错误 -Invalid tags produce errors during registration: +注册阶段若标签非法会报错: ```go type BadStruct struct { @@ -287,15 +284,15 @@ err := f.RegisterStruct(BadStruct{}, 1) ## 最佳实践 -1. **Use `-` for sensitive data**: Passwords, tokens, internal state -2. **Enable ref tracking for shared objects**: When the same pointer appears multiple times -3. **Disable ref tracking for simple fields**: Optimization when you know the field is unique -4. **Keep names consistent**: Cross-language names should match -5. **Document tag usage**: Especially for non-obvious configurations +1. **敏感字段使用 `-`**:如密码、令牌、内部状态 +2. **共享对象启用 ref**:同一指针可能多次出现时开启 +3. **简单唯一字段禁用 ref**:可做性能优化 +4. **保持命名一致**:跨语言字段名应保持稳定 +5. **记录标签意图**:非显式配置建议补充注释说明 -## Common Patterns +## 常见模式 -### Ignoring Computed Fields +### 忽略计算字段 ```go type Rectangle struct { @@ -309,7 +306,7 @@ func (r *Rectangle) ComputeArea() { } ``` -### Circular Structure with Parent +### 带父指针的循环结构 ```go type TreeNode struct { @@ -319,7 +316,7 @@ type TreeNode struct { } ``` -### Mixed Serialization Needs +### 混合序列化需求 ```go type Session struct { @@ -333,6 +330,6 @@ type Session struct { ## 相关主题 -- [References](references.md) -- [Basic Serialization](basic-serialization.md) -- [Schema Evolution](schema-evolution.md) +- [引用](references.md) +- [基础序列化](basic-serialization.md) +- [Schema 演进](schema-evolution.md) diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/java/field-configuration.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/java/field-configuration.md index 0182eeb129..2f21ab6c69 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/java/field-configuration.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/java/field-configuration.md @@ -19,31 +19,28 @@ license: | limitations under the License. --- -> 中文导读:本页介绍字段级序列化配置,包括字段 ID、可空控制、引用跟踪、忽略字段与动态类型控制等。 -> 建议在跨语言和兼容模式场景中优先显式配置字段 ID,并在需要时开启 ref/nullable 以保证行为一致。 - 本页说明如何在 Java 中配置序列化字段级元信息。 ## 概述 Apache ForyTM 通过注解提供字段级配置: -- **`@ForyField`**: Configure field metadata (id, nullable, ref, dynamic) -- **`@Ignore`**: Exclude fields from serialization -- **Integer type annotations**: Control integer encoding (varint, fixed, tagged, unsigned) +- **`@ForyField`**:配置字段元信息(id、nullable、ref、dynamic) +- **`@Ignore`**:将字段排除在序列化之外 +- **整数类型注解**:控制整数编码方式(varint、fixed、tagged、unsigned) -This enables: +这些能力可用于: -- **Tag IDs**: Assign compact numeric IDs to reduce struct field meta size overhead for compatible mode -- **Nullability**: Control whether fields can be null -- **Reference Tracking**: Enable reference tracking for shared objects -- **Field Skipping**: Exclude fields from serialization -- **Encoding Control**: Specify how integers are encoded -- **Polymorphism Control**: Control type info writing for struct fields +- **Tag ID**:为兼容模式分配紧凑数值 ID,降低 struct 字段元信息开销 +- **可空控制**:声明字段是否允许为 null +- **引用跟踪**:为共享对象开启引用跟踪 +- **字段跳过**:显式排除不需要序列化的字段 +- **编码控制**:指定整数序列化编码策略 +- **多态控制**:控制 struct 字段是否写入运行时类型信息 ## 基本语法 -Use annotations on fields: +在字段上使用注解: ```java import org.apache.fory.annotation.ForyField; @@ -60,9 +57,9 @@ public class Person { } ``` -## The `@ForyField` Annotation +## `@ForyField` 注解 -Use `@ForyField` to configure field-level metadata: +使用 `@ForyField` 配置字段级元信息: ```java public class User { @@ -85,16 +82,16 @@ public class User { ### 参数 -| Parameter | Type | Default | Description | +| 参数 | 类型 | 默认值 | 说明 | | ---------- | --------- | ------- | -------------------------------------- | -| `id` | `int` | `-1` | Field tag ID (-1 = use field name) | -| `nullable` | `boolean` | `false` | Whether the field can be null | -| `ref` | `boolean` | `false` | Enable reference tracking | -| `dynamic` | `Dynamic` | `AUTO` | Control polymorphism for struct fields | +| `id` | `int` | `-1` | 字段 tag ID(`-1` 表示使用字段名编码) | +| `nullable` | `boolean` | `false` | 字段是否可为 null | +| `ref` | `boolean` | `false` | 是否开启引用跟踪 | +| `dynamic` | `Dynamic` | `AUTO` | 控制 struct 字段多态行为 | -## Field ID (`id`) +## 字段 ID(`id`) -Assigns a numeric ID to a field to minimize struct field meta size overhead for compatible mode: +通过为字段分配数值 ID,可降低兼容模式下 struct 字段元信息开销: ```java public class User { @@ -109,21 +106,21 @@ public class User { } ``` -**Benefits**: +**收益:** -- Smaller serialized size (numeric IDs vs field names in metadata) -- Reduced struct field meta overhead -- Allows renaming fields without breaking binary compatibility +- 序列化体积更小(元信息里用数值 ID 而不是字段名) +- struct 字段元信息开销更低 +- 可在不破坏二进制兼容性的前提下重命名字段 -**Recommendation**: It is recommended to configure field IDs for compatible mode since it reduces serialization cost. +**建议:** 兼容模式下建议配置字段 ID,以降低序列化成本。 -**Notes**: +**注意:** -- IDs must be unique within a class -- IDs must be >= 0 (use -1 to use field name encoding, which is the default) -- If not specified, field name is used in metadata (larger overhead) +- 同一个类内 ID 必须唯一 +- ID 必须 `>= 0`(`-1` 表示使用字段名编码,也是默认行为) +- 未指定时,元信息将写字段名(开销更大) -**Without field IDs** (field names used in metadata): +**不配置字段 ID**(元信息使用字段名)示例: ```java public class User { @@ -132,39 +129,39 @@ public class User { } ``` -## Nullable Fields (`nullable`) +## 可空字段(`nullable`) -Use `nullable = true` for fields that can be `null`: +对可能为 `null` 的字段使用 `nullable = true`: ```java public class Record { - // Nullable string field + // 可空字符串字段 @ForyField(id = 0, nullable = true) private String optionalName; - // Nullable Integer field (boxed type) + // 可空 Integer 字段(装箱类型) @ForyField(id = 1, nullable = true) private Integer optionalCount; - // Non-nullable field (default) + // 非可空字段(默认) @ForyField(id = 2) private String requiredName; } ``` -**Notes**: +**注意:** -- Default is `nullable = false` (non-nullable) -- When `nullable = false`, Fory skips writing the null flag (saves 1 byte) -- Boxed types (`Integer`, `Long`, etc.) that can be null should use `nullable = true` +- 默认是 `nullable = false`(不可空) +- `nullable = false` 时,Fory 会省略 null 标记写入(节省 1 字节) +- 可能为 null 的装箱类型(`Integer`、`Long` 等)建议显式设为 `nullable = true` -## Reference Tracking (`ref`) +## 引用跟踪(`ref`) -Enable reference tracking for fields that may be shared or circular: +对于可能共享或循环引用的字段,启用引用跟踪: ```java public class RefOuter { - // Both fields may point to the same inner object + // 两个字段可能指向同一个内部对象 @ForyField(id = 0, ref = true, nullable = true) private RefInner inner1; @@ -176,56 +173,56 @@ public class CircularRef { @ForyField(id = 0) private String name; - // Self-referencing field for circular references + // 自引用字段,用于循环引用 @ForyField(id = 1, ref = true, nullable = true) private CircularRef selfRef; } ``` -**Use Cases**: +**适用场景:** -- Enable for fields that may be circular or shared -- When the same object is referenced from multiple fields +- 字段可能形成循环或共享关系 +- 同一对象被多个字段引用 -**Notes**: +**注意:** -- Default is `ref = false` (no reference tracking) -- When `ref = false`, avoids IdentityMap overhead and skips ref tracking flag -- Reference tracking only takes effect when global ref tracking is enabled +- 默认是 `ref = false`(不跟踪引用) +- `ref = false` 可避免 IdentityMap 开销,也会跳过引用跟踪标记 +- 仅在全局启用 ref tracking 时,字段级 ref 才生效 -## Dynamic (Polymorphism Control) +## Dynamic(多态控制) -Controls polymorphism behavior for struct fields in cross-language serialization: +控制跨语言序列化时 struct 字段的多态行为: ```java public class Container { - // AUTO: Interface/abstract types are dynamic, concrete types are not + // AUTO:接口/抽象类型动态,具体类型非动态 @ForyField(id = 0, dynamic = ForyField.Dynamic.AUTO) - private Animal animal; // Interface - type info written + private Animal animal; // 接口类型,写入类型信息 - // FALSE: No type info written, uses declared type's serializer + // FALSE:不写类型信息,直接按声明类型序列化 @ForyField(id = 1, dynamic = ForyField.Dynamic.FALSE) - private Dog dog; // Concrete - no type info + private Dog dog; // 具体类型,不写类型信息 - // TRUE: Type info written to support runtime subtypes + // TRUE:写类型信息,支持运行时子类型 @ForyField(id = 2, dynamic = ForyField.Dynamic.TRUE) - private Object data; // Force polymorphic + private Object data; // 强制多态 } ``` -**Options**: +**取值:** -| Value | Description | -| ------- | ------------------------------------------------------------------- | -| `AUTO` | Auto-detect: interface/abstract are dynamic, concrete types are not | -| `FALSE` | No type info written, uses declared type's serializer directly | -| `TRUE` | Type info written to support subtypes at runtime | +| 值 | 说明 | +| ------- | ------------------------------------------- | +| `AUTO` | 自动判断:接口/抽象类型动态,具体类型非动态 | +| `FALSE` | 不写类型信息,直接使用声明类型的序列化器 | +| `TRUE` | 写入类型信息,以支持运行时子类型 | -## Skipping Fields +## 跳过字段 -### Using `@Ignore` +### 使用 `@Ignore` -Exclude fields from serialization: +将字段排除在序列化之外: ```java import org.apache.fory.annotation.Ignore; @@ -238,69 +235,69 @@ public class User { private String name; @Ignore - private String password; // Not serialized + private String password; // 不序列化 @Ignore - private Object internalState; // Not serialized + private Object internalState; // 不序列化 } ``` -### Using `transient` +### 使用 `transient` -Java's `transient` keyword also excludes fields: +Java 的 `transient` 关键字同样会排除字段: ```java public class User { @ForyField(id = 0) private long id; - private transient String password; // Not serialized - private transient Object cache; // Not serialized + private transient String password; // 不序列化 + private transient Object cache; // 不序列化 } ``` -## Integer Type Annotations +## 整数类型注解 -Fory provides annotations to control integer encoding for cross-language compatibility. +Fory 提供整数注解,用于在跨语言场景中控制编码方式。 -### Signed 32-bit Integer (`@Int32Type`) +### 有符号 32 位整数(`@Int32Type`) ```java import org.apache.fory.annotation.Int32Type; public class MyStruct { - // Variable-length encoding (default) - compact for small values + // 变长编码(默认),小值更紧凑 @Int32Type(compress = true) private int compactId; - // Fixed 4-byte encoding - consistent size + // 固定 4 字节编码,长度稳定 @Int32Type(compress = false) private int fixedId; } ``` -### Signed 64-bit Integer (`@Int64Type`) +### 有符号 64 位整数(`@Int64Type`) ```java import org.apache.fory.annotation.Int64Type; import org.apache.fory.config.LongEncoding; public class MyStruct { - // Variable-length encoding (default) + // 变长编码(默认) @Int64Type(encoding = LongEncoding.VARINT) private long compactId; - // Fixed 8-byte encoding + // 固定 8 字节编码 @Int64Type(encoding = LongEncoding.FIXED) private long fixedTimestamp; - // Tagged encoding (4 bytes for small values, 9 bytes otherwise) + // tagged 编码(小值 4 字节,否则 9 字节) @Int64Type(encoding = LongEncoding.TAGGED) private long taggedValue; } ``` -### Unsigned Integers +### 无符号整数 ```java import org.apache.fory.annotation.Uint8Type; @@ -310,23 +307,23 @@ import org.apache.fory.annotation.Uint64Type; import org.apache.fory.config.LongEncoding; public class UnsignedStruct { - // Unsigned 8-bit [0, 255] + // 无符号 8 位 [0, 255] @Uint8Type private short flags; - // Unsigned 16-bit [0, 65535] + // 无符号 16 位 [0, 65535] @Uint16Type private int port; - // Unsigned 32-bit with varint encoding (default) + // 无符号 32 位,varint 编码(默认) @Uint32Type(compress = true) private long compactCount; - // Unsigned 32-bit with fixed encoding + // 无符号 32 位,fixed 编码 @Uint32Type(compress = false) private long fixedCount; - // Unsigned 64-bit with various encodings + // 无符号 64 位,多种编码 @Uint64Type(encoding = LongEncoding.VARINT) private long varintU64; @@ -338,31 +335,31 @@ public class UnsignedStruct { } ``` -### Encoding Summary +### 编码汇总 -| Annotation | Type ID | Encoding | Size | -| -------------------------------- | ------- | -------- | ------------ | -| `@Int32Type(compress = true)` | 5 | varint | 1-5 bytes | -| `@Int32Type(compress = false)` | 4 | fixed | 4 bytes | -| `@Int64Type(encoding = VARINT)` | 7 | varint | 1-10 bytes | -| `@Int64Type(encoding = FIXED)` | 6 | fixed | 8 bytes | -| `@Int64Type(encoding = TAGGED)` | 8 | tagged | 4 or 9 bytes | -| `@Uint8Type` | 9 | fixed | 1 byte | -| `@Uint16Type` | 10 | fixed | 2 bytes | -| `@Uint32Type(compress = true)` | 12 | varint | 1-5 bytes | -| `@Uint32Type(compress = false)` | 11 | fixed | 4 bytes | -| `@Uint64Type(encoding = VARINT)` | 14 | varint | 1-10 bytes | -| `@Uint64Type(encoding = FIXED)` | 13 | fixed | 8 bytes | -| `@Uint64Type(encoding = TAGGED)` | 15 | tagged | 4 or 9 bytes | +| 注解 | Type ID | 编码 | 大小 | +| -------------------------------- | ------- | ------ | ----------- | +| `@Int32Type(compress = true)` | 5 | varint | 1-5 字节 | +| `@Int32Type(compress = false)` | 4 | fixed | 4 字节 | +| `@Int64Type(encoding = VARINT)` | 7 | varint | 1-10 字节 | +| `@Int64Type(encoding = FIXED)` | 6 | fixed | 8 字节 | +| `@Int64Type(encoding = TAGGED)` | 8 | tagged | 4 或 9 字节 | +| `@Uint8Type` | 9 | fixed | 1 字节 | +| `@Uint16Type` | 10 | fixed | 2 字节 | +| `@Uint32Type(compress = true)` | 12 | varint | 1-5 字节 | +| `@Uint32Type(compress = false)` | 11 | fixed | 4 字节 | +| `@Uint64Type(encoding = VARINT)` | 14 | varint | 1-10 字节 | +| `@Uint64Type(encoding = FIXED)` | 13 | fixed | 8 字节 | +| `@Uint64Type(encoding = TAGGED)` | 15 | tagged | 4 或 9 字节 | -**When to Use**: +**何时使用:** -- `varint`: Best for values that are often small (default) -- `fixed`: Best for values that use full range (e.g., timestamps, hashes) -- `tagged`: Good balance between size and performance -- Unsigned types: For cross-language compatibility with Rust, Go, C++ +- `varint`:数值通常较小时最优(默认) +- `fixed`:数值分布接近全范围时更稳定(如时间戳、哈希) +- `tagged`:在体积与性能间平衡较好 +- 无符号类型:适合与 Rust/Go/C++ 等语言进行无符号整数互操作 -## Complete Example +## 完整示例 ```java import org.apache.fory.Fory; @@ -377,18 +374,18 @@ import java.util.Map; import java.util.Set; public class Document { - // Fields with tag IDs (recommended for compatible mode) + // 带 tag ID 的字段(兼容模式推荐) @ForyField(id = 0) private String title; @ForyField(id = 1) private int version; - // Nullable field + // 可空字段 @ForyField(id = 2, nullable = true) private String description; - // Collection fields + // 集合字段 @ForyField(id = 3) private List tags; @@ -398,24 +395,24 @@ public class Document { @ForyField(id = 5) private Set categories; - // Integer with different encodings + // 不同编码方式的整数 @ForyField(id = 6) @Uint64Type(encoding = LongEncoding.VARINT) - private long viewCount; // varint encoding + private long viewCount; // varint 编码 @ForyField(id = 7) @Uint64Type(encoding = LongEncoding.FIXED) - private long fileSize; // fixed encoding + private long fileSize; // fixed 编码 @ForyField(id = 8) @Uint64Type(encoding = LongEncoding.TAGGED) - private long checksum; // tagged encoding + private long checksum; // tagged 编码 - // Reference-tracked field for shared/circular references + // 共享/循环引用字段 @ForyField(id = 9, ref = true, nullable = true) private Document parent; - // Ignored field (not serialized) + // 忽略字段(不序列化) private transient Object cache; // Getters and setters... @@ -446,13 +443,13 @@ public class Main { } ``` -## Cross-Language Compatibility +## 跨语言兼容 -When serializing data to be read by other languages (Python, Rust, C++, Go), use field IDs and matching type annotations: +当数据需要被其他语言(Python、Rust、C++、Go)读取时,建议使用字段 ID 并配套类型注解: ```java public class CrossLangData { - // Use field IDs for cross-language compatibility + // 使用字段 ID 保证跨语言兼容 @ForyField(id = 0) @Int32Type(compress = true) private int intVar; @@ -470,9 +467,9 @@ public class CrossLangData { } ``` -## Schema Evolution +## Schema 演进 -Compatible mode supports schema evolution. It is recommended to configure field IDs to reduce serialization cost: +兼容模式支持 Schema 演进。建议配置字段 ID 以降低序列化成本: ```java // Version 1 @@ -497,9 +494,9 @@ public class DataV2 { } ``` -Data serialized with V1 can be deserialized with V2 (new field will be `null`). +V1 写入的数据可由 V2 读取(新增字段会是 `null`)。 -Alternatively, field IDs can be omitted (field names will be used in metadata with larger overhead): +也可以不配置字段 ID(元信息会使用字段名,开销更大): ```java public class Data { @@ -508,23 +505,23 @@ public class Data { } ``` -## Native Mode vs Xlang Mode +## Native 模式与 Xlang 模式 -Field configuration behaves differently depending on the serialization mode: +字段配置在不同序列化模式下的默认行为不同。 -### Native Mode (Java-only) +### Native 模式(仅 Java) -Native mode has **relaxed default values** for maximum compatibility: +Native 模式以最大兼容性为目标,默认值更宽松: -- **Nullable**: Reference types are nullable by default -- **Ref tracking**: Enabled by default for object references (except `String`, boxed types, and time types) -- **Polymorphism**: All non-final classes support polymorphism by default +- **Nullable**:引用类型默认可空 +- **Ref tracking**:对象引用默认开启(`String`、装箱类型、时间类型除外) +- **Polymorphism**:所有非 final 类默认支持多态 -In native mode, you typically **don't need to configure field annotations** unless you want to: +在 Native 模式下,通常**不需要额外字段注解**,除非你希望: -- Reduce serialized size by using field IDs -- Optimize performance by disabling unnecessary ref tracking -- Control integer encoding for specific fields +- 用字段 ID 降低体积 +- 关闭不必要的 ref 跟踪以优化性能 +- 对特定字段精确控制整数编码 ```java // Native mode: works without any annotations @@ -535,20 +532,20 @@ public class User { } ``` -### Xlang Mode (Cross-language) +### Xlang 模式(跨语言) -Xlang mode has **stricter default values** due to type system differences between languages: +由于不同语言类型系统差异,Xlang 模式默认值更严格: -- **Nullable**: Fields are non-nullable by default (`nullable = false`) -- **Ref tracking**: Disabled by default (`ref = false`) -- **Polymorphism**: Concrete types are non-polymorphic by default +- **Nullable**:字段默认不可空(`nullable = false`) +- **Ref tracking**:默认关闭(`ref = false`) +- **Polymorphism**:具体类型默认不写多态类型信息 -In xlang mode, you **need to configure fields** when: +在 Xlang 模式下,以下情况需要显式配置: -- A field can be null (use `nullable = true`) -- A field needs reference tracking for shared/circular objects (use `ref = true`) -- Integer types need specific encoding for cross-language compatibility -- You want to reduce metadata size (use field IDs) +- 字段可能为 null(使用 `nullable = true`) +- 字段需要共享/循环引用语义(使用 `ref = true`) +- 整数类型需要为跨语言兼容指定编码 +- 你希望减少元信息大小(使用字段 ID) ```java // Xlang mode: explicit configuration required for nullable/ref fields @@ -567,42 +564,42 @@ public class User { } ``` -### Default Values Summary - -| Option | Native Mode Default | Xlang Mode Default | -| ---------- | ------------------------ | --------------------------------- | -| `nullable` | `true` (reference types) | `false` | -| `ref` | `true` | `false` | -| `dynamic` | `true` (non-final) | `AUTO` (concrete types are final) | - -## Best Practices - -1. **Configure field IDs**: Recommended for compatible mode to reduce serialization cost -2. **Use `nullable = true` for nullable fields**: Required for fields that can be null -3. **Enable ref tracking for shared objects**: Use `ref = true` when objects are shared or circular -4. **Use `@Ignore` or `transient` for sensitive data**: Passwords, tokens, internal state -5. **Choose appropriate encoding**: `varint` for small values, `fixed` for full-range values -6. **Keep IDs stable**: Once assigned, don't change field IDs -7. **Configure unsigned types for cross-language compatibility**: When interoperating with unsigned numbers in Rust, Go, C++ - -## Annotations Reference - -| Annotation | Description | -| ----------------------------- | -------------------------------------- | -| `@ForyField(id = N)` | Field tag ID to reduce metadata size | -| `@ForyField(nullable = true)` | Mark field as nullable | -| `@ForyField(ref = true)` | Enable reference tracking | -| `@ForyField(dynamic = ...)` | Control polymorphism for struct fields | -| `@Ignore` | Exclude field from serialization | -| `@Int32Type(compress = ...)` | 32-bit signed integer encoding | -| `@Int64Type(encoding = ...)` | 64-bit signed integer encoding | -| `@Uint8Type` | Unsigned 8-bit integer | -| `@Uint16Type` | Unsigned 16-bit integer | -| `@Uint32Type(compress = ...)` | Unsigned 32-bit integer encoding | -| `@Uint64Type(encoding = ...)` | Unsigned 64-bit integer encoding | - -## Related Topics - -- [Basic Serialization](basic_serialization) - Getting started with Fory serialization -- [Schema Evolution](schema_evolution) - Compatible mode and schema evolution -- [Cross-Language](cross_language) - Interoperability with Python, Rust, C++, Go +### 默认值汇总 + +| 选项 | Native 模式默认值 | Xlang 模式默认值 | +| ---------- | --------------------- | ---------------------------------- | +| `nullable` | `true`(引用类型) | `false` | +| `ref` | `true` | `false` | +| `dynamic` | `true`(非 final 类) | `AUTO`(具体类型通常按非动态处理) | + +## 最佳实践 + +1. **配置字段 ID**:兼容模式下建议配置,降低序列化成本 +2. **可空字段使用 `nullable = true`**:对可为 null 的字段必须显式声明 +3. **共享对象开启 `ref`**:对象共享或循环时使用 `ref = true` +4. **敏感字段用 `@Ignore` 或 `transient`**:如密码、令牌、内部状态 +5. **选择合适编码**:小值用 `varint`,全范围值用 `fixed` +6. **保持 ID 稳定**:一旦分配,不要随意改动字段 ID +7. **跨语言场景显式无符号类型**:与 Rust、Go、C++ 互操作时尤其重要 + +## 注解速查 + +| 注解 | 说明 | +| ----------------------------- | ------------------------------- | +| `@ForyField(id = N)` | 配置字段 tag ID,减少元信息开销 | +| `@ForyField(nullable = true)` | 将字段标记为可空 | +| `@ForyField(ref = true)` | 为字段启用引用跟踪 | +| `@ForyField(dynamic = ...)` | 控制 struct 字段多态行为 | +| `@Ignore` | 将字段排除在序列化之外 | +| `@Int32Type(compress = ...)` | 32 位有符号整数编码 | +| `@Int64Type(encoding = ...)` | 64 位有符号整数编码 | +| `@Uint8Type` | 8 位无符号整数 | +| `@Uint16Type` | 16 位无符号整数 | +| `@Uint32Type(compress = ...)` | 32 位无符号整数编码 | +| `@Uint64Type(encoding = ...)` | 64 位无符号整数编码 | + +## 相关主题 + +- [基础序列化](basic_serialization) - 快速上手 Fory 序列化 +- [Schema 演进](schema_evolution) - 兼容模式与 schema 演进 +- [跨语言](cross_language) - 与 Python、Rust、C++、Go 互操作 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/python/field-configuration.md b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/python/field-configuration.md index fb489d283b..65d7b04281 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/python/field-configuration.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/version-0.15/guide/python/field-configuration.md @@ -19,31 +19,28 @@ license: | limitations under the License. --- -> 中文导读:本页介绍字段级序列化配置,包括字段 ID、可空控制、引用跟踪、忽略字段与动态类型控制等。 -> 建议在跨语言和兼容模式场景中优先显式配置字段 ID,并在需要时开启 ref/nullable 以保证行为一致。 - 本页说明如何在 Python 中配置序列化字段级元信息。 ## 概述 -Apache ForyTM 通过以下方式提供字段级配置: +Apache ForyTM 通过以下机制提供字段级配置: -- **`pyfory.field()`**: Configure field metadata (id, nullable, ref, ignore, dynamic) -- **Type annotations**: Control integer encoding (varint, fixed, tagged) -- **`Optional[T]`**: Mark fields as nullable +- **`pyfory.field()`**:配置字段元信息(id、nullable、ref、ignore、dynamic) +- **类型注解**:控制整数编码(varint、fixed、tagged) +- **`Optional[T]`**:标记字段可空 -This enables: +这些能力可用于: -- **Tag IDs**: Assign compact numeric IDs to reduce struct field meta size overhead -- **Nullability**: Control whether fields can be null -- **Reference Tracking**: Enable reference tracking for shared objects -- **Field Skipping**: Exclude fields from serialization -- **Encoding Control**: Specify how integers are encoded (varint, fixed, tagged) -- **Polymorphism**: Control whether type info is written for struct fields +- **Tag ID**:分配紧凑数值 ID,降低 struct 字段元信息开销 +- **可空控制**:声明字段是否可为 null/None +- **引用跟踪**:为共享对象启用引用跟踪 +- **字段跳过**:从序列化中排除字段 +- **编码控制**:指定整数编码方式(varint、fixed、tagged) +- **多态控制**:控制 struct 字段是否写入类型信息 ## 基本语法 -Use `@dataclass` decorator with type annotations and `pyfory.field()`: +结合 `@dataclass`、类型注解与 `pyfory.field()`: ```python from dataclasses import dataclass @@ -59,7 +56,7 @@ class Person: ## `pyfory.field()` 函数 -Use `pyfory.field()` to configure field-level metadata: +使用 `pyfory.field()` 配置字段级元信息: ```python @dataclass @@ -73,19 +70,19 @@ class User: ### 参数 -| Parameter | Type | Default | Description | -| ----------------- | -------- | --------- | ------------------------------------ | -| `id` | `int` | `-1` | Field tag ID (-1 = use field name) | -| `nullable` | `bool` | `False` | Whether the field can be null | -| `ref` | `bool` | `False` | Enable reference tracking | -| `ignore` | `bool` | `False` | Exclude field from serialization | -| `dynamic` | `bool` | `None` | Control whether type info is written | -| `default` | Any | `MISSING` | Default value for the field | -| `default_factory` | Callable | `MISSING` | Factory function for default value | +| 参数 | 类型 | 默认值 | 说明 | +| ----------------- | -------- | --------- | ---------------------------------- | +| `id` | `int` | `-1` | 字段 tag ID(`-1` 表示使用字段名) | +| `nullable` | `bool` | `False` | 字段是否可为 null/None | +| `ref` | `bool` | `False` | 是否启用引用跟踪 | +| `ignore` | `bool` | `False` | 是否从序列化中排除 | +| `dynamic` | `bool` | `None` | 控制是否写入类型信息 | +| `default` | Any | `MISSING` | 字段默认值 | +| `default_factory` | Callable | `MISSING` | 默认值工厂函数 | -## Field ID (`id`) +## 字段 ID(`id`) -Assigns a numeric ID to a field to minimize struct field meta size overhead: +通过给字段分配数值 ID,可减少 struct 字段元信息开销: ```python @dataclass @@ -95,21 +92,21 @@ class User: age: pyfory.int32 = pyfory.field(id=2, default=0) ``` -**Benefits**: +**收益:** -- Smaller serialized size (numeric IDs vs field names in metadata) -- Reduced struct field meta overhead -- Allows renaming fields without breaking binary compatibility +- 序列化体积更小(元信息中数值 ID 替代字段名) +- struct 字段元信息开销更低 +- 字段重命名时可保持二进制兼容 -**Recommendation**: It is recommended to configure field IDs for compatible mode since it reduces serialization cost. +**建议:** 兼容模式下建议配置字段 ID,以降低序列化成本。 -**Notes**: +**注意:** -- IDs must be unique within a class -- IDs must be >= 0 (use -1 to use field name encoding, which is the default) -- If not specified, field name is used in metadata (larger overhead) +- 同一类内 ID 必须唯一 +- ID 必须 `>= 0`(`-1` 表示使用字段名编码,默认行为) +- 未指定时会使用字段名写入元信息(开销更大) -**Without field IDs** (field names used in metadata): +**不配置字段 ID**(元信息使用字段名)示例: ```python @dataclass @@ -118,35 +115,35 @@ class User: name: str = "" ``` -## Nullable Fields (`nullable`) +## 可空字段(`nullable`) -Use `nullable=True` for fields that can be `None`: +对可能为 `None` 的字段使用 `nullable=True`: ```python from typing import Optional @dataclass class Record: - # Nullable string field + # 可空字符串字段 optional_name: Optional[str] = pyfory.field(id=0, nullable=True, default=None) - # Nullable integer field + # 可空整数字段 optional_count: Optional[pyfory.int32] = pyfory.field(id=1, nullable=True, default=None) ``` -**Notes**: +**注意:** -- `Optional[T]` fields must have `nullable=True` -- Non-optional fields default to `nullable=False` +- `Optional[T]` 字段应配合 `nullable=True` +- 非 Optional 字段默认 `nullable=False` -## Reference Tracking (`ref`) +## 引用跟踪(`ref`) -Enable reference tracking for fields that may be shared or circular: +对于可能共享或循环引用的字段启用引用跟踪: ```python @dataclass class RefOuter: - # Both fields may point to the same inner object + # 两个字段可能指向同一个内部对象 inner1: Optional[RefInner] = pyfory.field(id=0, ref=True, nullable=True, default=None) inner2: Optional[RefInner] = pyfory.field(id=1, ref=True, nullable=True, default=None) @@ -154,37 +151,37 @@ class RefOuter: @dataclass class CircularRef: name: str = pyfory.field(id=0, default="") - # Self-referencing field for circular references + # 自引用字段,用于循环引用 self_ref: Optional["CircularRef"] = pyfory.field(id=1, ref=True, nullable=True, default=None) ``` -**Use Cases**: +**适用场景:** -- Enable for fields that may be circular or shared -- When the same object is referenced from multiple fields +- 字段可能形成循环或共享关系 +- 同一对象被多个字段引用 -**Notes**: +**注意:** -- Reference tracking only takes effect when `Fory(ref=True)` is set globally -- Field-level `ref=True` AND global `ref=True` must both be enabled +- 只有全局设置 `Fory(ref=True)` 时,引用跟踪才生效 +- 字段级 `ref=True` 与全局 `ref=True` 必须同时开启 -## Skipping Fields (`ignore`) +## 跳过字段(`ignore`) -Exclude fields from serialization: +将字段排除在序列化之外: ```python @dataclass class User: id: pyfory.int64 = pyfory.field(id=0, default=0) name: str = pyfory.field(id=1, default="") - # Not serialized + # 不序列化 _cache: dict = pyfory.field(ignore=True, default_factory=dict) _internal_state: str = pyfory.field(ignore=True, default="") ``` -## Dynamic Fields (`dynamic`) +## Dynamic 字段(`dynamic`) -Control whether type information is written for struct fields. This is essential for polymorphism support: +控制 struct 字段是否写入类型信息,这是支持多态的关键: ```python from abc import ABC, abstractmethod @@ -203,36 +200,36 @@ class Circle(Shape): @dataclass class Container: - # Abstract class: dynamic is always True (type info written) + # 抽象类:dynamic 总为 True(写类型信息) shape: Shape = pyfory.field(id=0) - # Force type info for concrete type (support runtime subtypes) + # 对具体类型强制写类型信息(支持运行时子类) circle: Circle = pyfory.field(id=1, dynamic=True) - # Skip type info for concrete type (use declared type directly) + # 对具体类型跳过类型信息(按声明类型处理) fixed_circle: Circle = pyfory.field(id=2, dynamic=False) ``` -**Default Behavior**: +**默认行为:** -| Mode | Abstract Class | Concrete Object Types | Numeric/str/time Types | -| ----------- | -------------- | --------------------- | ---------------------- | -| Native mode | `True` | `True` | `False` | -| Xlang mode | `True` | `False` | `False` | +| 模式 | 抽象类 | 具体对象类型 | 数值/str/time 类型 | +| ----------- | ------ | ------------ | ------------------ | +| Native 模式 | `True` | `True` | `False` | +| Xlang 模式 | `True` | `False` | `False` | -**Notes**: +**注意:** -- **Abstract classes**: `dynamic` is always `True` (type info must be written) -- **Native mode**: `dynamic` defaults to `True` for object types, `False` for numeric/str/time types -- **Xlang mode**: `dynamic` defaults to `False` for concrete types -- Use `dynamic=True` when a concrete field may hold subclass instances -- Use `dynamic=False` for performance optimization when type is known +- **抽象类**:`dynamic` 始终为 `True`(必须写类型信息) +- **Native 模式**:对象类型默认 `dynamic=True`;数值/str/time 默认 `False` +- **Xlang 模式**:具体类型默认 `dynamic=False` +- 当具体字段可能持有子类实例时,使用 `dynamic=True` +- 当类型固定且追求性能时,可使用 `dynamic=False` -## Integer Type Annotations +## 整数类型注解 -Fory provides type annotations to control integer encoding: +Fory 提供类型注解来控制整数编码。 -### Signed Integers +### 有符号整数 ```python @dataclass @@ -243,7 +240,7 @@ class SignedIntegers: long_val: pyfory.int64 = 0 # 64-bit signed (varint encoding) ``` -### Unsigned Integers +### 无符号整数 ```python @dataclass @@ -264,7 +261,7 @@ class UnsignedIntegers: u64_tagged: pyfory.tagged_uint64 = 0 # 64-bit unsigned (tagged) ``` -### Floating Point +### 浮点数 ```python @dataclass @@ -273,31 +270,31 @@ class FloatingPoint: double_val: pyfory.float64 = 0.0 # 64-bit double ``` -### Encoding Summary +### 编码汇总 -| Type | Encoding | Size | -| ---------------------- | -------- | ---------- | -| `pyfory.int8` | fixed | 1 byte | -| `pyfory.int16` | fixed | 2 bytes | -| `pyfory.int32` | varint | 1-5 bytes | -| `pyfory.int64` | varint | 1-10 bytes | -| `pyfory.uint8` | fixed | 1 byte | -| `pyfory.uint16` | fixed | 2 bytes | -| `pyfory.uint32` | varint | 1-5 bytes | -| `pyfory.uint64` | varint | 1-10 bytes | -| `pyfory.fixed_uint32` | fixed | 4 bytes | -| `pyfory.fixed_uint64` | fixed | 8 bytes | -| `pyfory.tagged_uint64` | tagged | 1-9 bytes | -| `pyfory.float32` | fixed | 4 bytes | -| `pyfory.float64` | fixed | 8 bytes | +| 类型 | 编码 | 大小 | +| ---------------------- | ------ | --------- | +| `pyfory.int8` | fixed | 1 字节 | +| `pyfory.int16` | fixed | 2 字节 | +| `pyfory.int32` | varint | 1-5 字节 | +| `pyfory.int64` | varint | 1-10 字节 | +| `pyfory.uint8` | fixed | 1 字节 | +| `pyfory.uint16` | fixed | 2 字节 | +| `pyfory.uint32` | varint | 1-5 字节 | +| `pyfory.uint64` | varint | 1-10 字节 | +| `pyfory.fixed_uint32` | fixed | 4 字节 | +| `pyfory.fixed_uint64` | fixed | 8 字节 | +| `pyfory.tagged_uint64` | tagged | 1-9 字节 | +| `pyfory.float32` | fixed | 4 字节 | +| `pyfory.float64` | fixed | 8 字节 | -**When to Use**: +**何时使用:** -- `varint`: Best for values that are often small (default for int32/int64/uint32/uint64) -- `fixed`: Best for values that use full range (e.g., timestamps, hashes) -- `tagged`: When type information needs to be preserved (uint64 only) +- `varint`:适合小值占多数的场景(int32/int64/uint32/uint64 默认) +- `fixed`:适合覆盖全值域的场景(例如时间戳、哈希) +- `tagged`:适合需要保留类型信息的场景(仅 uint64) -## Complete Example +## 完整示例 ```python from dataclasses import dataclass @@ -361,9 +358,9 @@ if __name__ == "__main__": main() ``` -## Cross-Language Compatibility +## 跨语言兼容 -When serializing data to be read by other languages (Java, Rust, C++, Go), use field IDs and matching type annotations: +当序列化数据将被其他语言(Java、Rust、C++、Go)读取时,建议使用字段 ID 并配套类型注解: ```python @dataclass @@ -375,9 +372,9 @@ class CrossLangData: optional_value: Optional[str] = pyfory.field(id=3, nullable=True, default=None) ``` -## Schema Evolution +## Schema 演进 -Compatible mode supports schema evolution. It is recommended to configure field IDs to reduce serialization cost: +兼容模式支持 Schema 演进。建议通过字段 ID 降低序列化成本: ```python # Version 1 @@ -395,9 +392,9 @@ class DataV2: email: Optional[str] = pyfory.field(id=2, nullable=True, default=None) # New field ``` -Data serialized with V1 can be deserialized with V2 (new field will be `None`). +V1 写出的数据可由 V2 读取(新增字段将为 `None`)。 -Alternatively, field IDs can be omitted (field names will be used in metadata with larger overhead): +也可以不配置字段 ID(此时元信息使用字段名,开销更大): ```python @dataclass @@ -406,21 +403,21 @@ class Data: name: str = "" ``` -## Native Mode vs Xlang Mode +## Native 模式与 Xlang 模式 -Field configuration behaves differently depending on the serialization mode: +字段配置会随序列化模式不同而变化。 -### Native Mode (Python-only) +### Native 模式(仅 Python) -Native mode has **relaxed default values** for maximum compatibility: +Native 模式默认值更宽松,以获得更高兼容性: -- **Nullable**: `str` and numeric types are non-nullable by default unless `Optional` is used -- **Ref tracking**: Enabled by default for object references (except `str` and numeric types) +- **Nullable**:`str` 和数值类型默认不可空,除非使用 `Optional` +- **Ref tracking**:对象引用默认开启(`str` 与数值类型除外) -In native mode, you typically **don't need to configure field annotations** unless you want to: +在 Native 模式中,通常**不需要显式字段配置**,除非你希望: -- Reduce serialized size by using field IDs -- Optimize performance by disabling unnecessary ref tracking +- 通过字段 ID 降低序列化体积 +- 关闭不必要的 ref 跟踪以优化性能 ```python # Native mode: works without field configuration @@ -431,19 +428,19 @@ class User: tags: List[str] = None ``` -### Xlang Mode (Cross-language) +### Xlang 模式(跨语言) -Xlang mode has **stricter default values** due to type system differences between languages: +由于语言间类型系统差异,Xlang 模式默认值更严格: -- **Nullable**: Fields are non-nullable by default (`nullable=False`) -- **Ref tracking**: Disabled by default (`ref=False`) +- **Nullable**:默认不可空(`nullable=False`) +- **Ref tracking**:默认关闭(`ref=False`) -In xlang mode, you **need to configure fields** when: +在 Xlang 模式中,以下情况需要显式配置: -- A field can be None (use `Optional[T]` with `nullable=True`) -- A field needs reference tracking for shared/circular objects (use `ref=True`) -- Integer types need specific encoding for cross-language compatibility -- You want to reduce metadata size (use field IDs) +- 字段可能为 None(`Optional[T]` + `nullable=True`) +- 字段需要共享/循环引用语义(`ref=True`) +- 整数类型需要指定跨语言编码 +- 需要减少元信息开销(字段 ID) ```python # Xlang mode: explicit configuration required for nullable/ref fields @@ -455,41 +452,41 @@ class User: friend: Optional["User"] = pyfory.field(id=3, ref=True, nullable=True, default=None) # Must declare ref ``` -### Default Values Summary - -| Option | Native Mode Default | Xlang Mode Default | -| ---------- | ----------------------------------------------------- | ------------------ | -| `nullable` | `False` for `str`/numeric; others nullable by default | `False` | -| `ref` | `True` (except `str` and numeric types) | `False` | -| `dynamic` | `True` (except numeric/str/time types) | `False` (concrete) | - -## Best Practices - -1. **Configure field IDs**: Recommended for compatible mode to reduce serialization cost -2. **Use `Optional[T]` with `nullable=True`**: Required for nullable fields in xlang mode -3. **Enable ref tracking for shared objects**: Use `ref=True` when objects are shared or circular -4. **Use `ignore=True` for sensitive data**: Passwords, tokens, internal state -5. **Choose appropriate encoding**: `varint` for small values, `fixed` for full-range values -6. **Keep IDs stable**: Once assigned, don't change field IDs - -## Options Reference - -| Configuration | Description | -| -------------------------------------------- | ------------------------------------ | -| `pyfory.field(id=N)` | Field tag ID to reduce metadata size | -| `pyfory.field(nullable=True)` | Mark field as nullable | -| `pyfory.field(ref=True)` | Enable reference tracking | -| `pyfory.field(ignore=True)` | Exclude field from serialization | -| `pyfory.field(dynamic=True)` | Force type info to be written | -| `pyfory.field(dynamic=False)` | Skip type info (use declared type) | -| `Optional[T]` | Type hint for nullable fields | -| `pyfory.int32`, `pyfory.int64` | Signed integers (varint encoding) | -| `pyfory.uint32`, `pyfory.uint64` | Unsigned integers (varint encoding) | -| `pyfory.fixed_uint32`, `pyfory.fixed_uint64` | Fixed-size unsigned | -| `pyfory.tagged_uint64` | Tagged encoding for uint64 | - -## Related Topics - -- [Basic Serialization](basic_serialization) - Getting started with Fory serialization -- [Schema Evolution](schema_evolution) - Compatible mode and schema evolution -- [Cross-Language](cross_language) - Interoperability with Java, Rust, C++, Go +### 默认值汇总 + +| 选项 | Native 模式默认值 | Xlang 模式默认值 | +| ---------- | ------------------------------------------ | ------------------- | +| `nullable` | `str`/数值类型为 `False`,其余对象通常可空 | `False` | +| `ref` | `True`(`str` 和数值类型除外) | `False` | +| `dynamic` | `True`(数值/str/time 类型除外) | `False`(具体类型) | + +## 最佳实践 + +1. **配置字段 ID**:兼容模式下建议配置,降低序列化成本 +2. **`Optional[T]` 配合 `nullable=True`**:xlang 下可空字段需要显式声明 +3. **共享对象启用 ref**:共享或循环关系使用 `ref=True` +4. **敏感字段使用 `ignore=True`**:例如密码、令牌、内部状态 +5. **选择合适编码**:小值用 `varint`,全范围值用 `fixed` +6. **保持 ID 稳定**:分配后不要更改字段 ID + +## 选项速查 + +| 配置 | 说明 | +| -------------------------------------------- | ------------------------------ | +| `pyfory.field(id=N)` | 字段 tag ID,减少元信息开销 | +| `pyfory.field(nullable=True)` | 标记字段可空 | +| `pyfory.field(ref=True)` | 启用引用跟踪 | +| `pyfory.field(ignore=True)` | 将字段排除在序列化之外 | +| `pyfory.field(dynamic=True)` | 强制写入类型信息 | +| `pyfory.field(dynamic=False)` | 跳过类型信息(按声明类型处理) | +| `Optional[T]` | 可空字段类型提示 | +| `pyfory.int32`, `pyfory.int64` | 有符号整数(varint 编码) | +| `pyfory.uint32`, `pyfory.uint64` | 无符号整数(varint 编码) | +| `pyfory.fixed_uint32`, `pyfory.fixed_uint64` | 定长无符号整数 | +| `pyfory.tagged_uint64` | uint64 的 tagged 编码 | + +## 相关主题 + +- [基础序列化](basic_serialization) - 快速上手 Fory 序列化 +- [Schema 演进](schema_evolution) - 兼容模式与 schema 演进 +- [跨语言](cross_language) - 与 Java、Rust、C++、Go 互操作 diff --git a/skills/translate-docs-zh/SKILL.md b/skills/translate-docs-zh/SKILL.md new file mode 100644 index 0000000000..4c46c06173 --- /dev/null +++ b/skills/translate-docs-zh/SKILL.md @@ -0,0 +1,158 @@ +--- +name: translate-docs-zh +description: Translate Apache Fory docs into Simplified Chinese and maintain existing Chinese translations by diffing English source changes. Use when asked to translate docs, sync i18n/zh-CN content, remove placeholder Chinese-intro notices, or update already-translated files after English docs changed. Strict rule: do NOT use any external translation service, API, website, or translation CLI tool; translation must be done directly by Codex. +--- + +# Translate Docs (zh-CN) + +Translate documentation into Simplified Chinese and keep existing Chinese docs aligned with English source updates. + +## Hard Constraints + +- Do not call external translation tools. +- Do not use translation websites/services/APIs (Google/Baidu/DeepL/Youdao/OpenAI translation API wrappers, etc.). +- Do not use local translation CLIs or plugins. +- Translate directly in-place by Codex reasoning and editing only. + +## Terminology Reference (Required) + +- Always apply the terminology standard in `references/terminology.md`. +- If existing Chinese wording conflicts with the terminology table, normalize to the table unless user explicitly requests otherwise. +- For newly introduced English terms, append a proposed entry to the terminology table when the term is likely to recur. + +## Path Mapping + +Map source and target paths with these rules: + +1. Current docs: + +- Source: `docs/.md` +- Target: `i18n/zh-CN/docusaurus-plugin-content-docs/current/.md` + +2. Versioned docs: + +- Source: `versioned_docs/version-X/.md` +- Target: `i18n/zh-CN/docusaurus-plugin-content-docs/version-X/.md` + +3. Category labels: + +- Source: `docs/**/_category_.json` +- Target: `i18n/zh-CN/docusaurus-plugin-content-docs/**/_category_.json` + +4. Sidebar top-level label i18n keys: + +- Target: `i18n/zh-CN/docusaurus-plugin-content-docs/current.json` +- Optional version keys: `i18n/zh-CN/docusaurus-plugin-content-docs/version-*.json` + +## Workflow + +### Step 1: Discover file pairs + +1. Build source-target pairs from user scope. +2. If user gives only Chinese targets, infer matching English source by reverse mapping. +3. Skip pairs whose source file does not exist; report them clearly. + +### Step 2: Classify each Chinese file + +Classify as `untranslated` or `translated`. + +Treat as `untranslated` if any condition is true: + +- Target file missing. +- Contains placeholder notices like `中文导读` / `中文章节导读`. +- Non-code prose is mostly English. +- Headings/body are largely English while only title/frontmatter is Chinese. + +Otherwise classify as `translated`. + +### Step 3A: Handle untranslated files (full translation) + +1. Translate the entire document from current English source. +2. Keep frontmatter keys and structure valid. +3. Keep identifiers/code/protocol fields/CLI flags in English. +4. Translate headings, prose, table descriptions, and comments meant for readers. +5. Remove placeholder intro notices (`中文导读` style blocks). +6. Preserve link targets and anchors unless a better Chinese heading requires an explicit anchor. + +### Step 3B: Handle translated files (diff-based maintenance) + +1. Find source changes since last Chinese update baseline. +2. Prefer this baseline method: + +- `zh_last_commit = git log -1 --format=%H -- ` +- `git diff --unified=0 ..HEAD -- ` + +3. If no source diff, keep Chinese file unchanged. +4. If source diff exists, decide update strategy: + +Use **partial update** when all are true: + +- Changes are local and limited. +- Document structure mostly unchanged. +- No widespread terminology shifts. + +Use **full rewrite** when any is true: + +- Large structural edits (section reordering/splitting/merging). +- Significant rewrite of core semantics. +- Many scattered edits across the document. +- Existing Chinese wording quality is inconsistent or outdated. + +5. Apply translations only for changed semantics; keep unaffected Chinese content stable. +6. If full rewrite is chosen, regenerate complete Chinese content from latest English source. + +## Translation Quality Rules + +1. Prioritize semantic correctness over literal wording. +2. Keep terminology consistent across files. +3. Avoid awkward literal phrases (for example avoid unnatural jargon calques). +4. Keep technical precision: + +- Distinguish encoding format vs transport framework concepts. +- Keep units, ranges, and bit layouts exact. + +5. Preserve examples and command behavior exactly. + +## Validation Checklist + +Run checks after edits: + +1. Placeholder cleanup: + +- `rg -n "中文导读|中文章节导读" i18n/zh-CN -S` + +2. Markdown integrity: + +- Ensure code fences are balanced. +- Ensure tables render (pipes/alignment valid). +- Ensure frontmatter remains valid YAML. + +3. MDX safety: + +- Avoid standalone lines that MDX may parse as ESM (`import ...`, `export ...`) in prose. + +4. Link/anchor sanity: + +- Preserve existing inbound anchors where possible. + +5. Optional build verification (recommended): + +- `npm run build -- --locale zh-CN` + +## Decision Heuristics for Rewrite vs Patch + +Use this pragmatic threshold (guide, not absolute): + +- Patch when source changed prose is small and localized. +- Rewrite when changed prose is broad, central, or distributed across many sections. + +When uncertain, prefer full rewrite for short/medium docs and targeted patch for very large docs with clearly isolated changes. + +## Output Requirements for the user + +Report clearly: + +1. Files fully translated. +2. Files partially updated by source diff. +3. Files fully rewritten due to large source changes. +4. Validation results and any unresolved risks. diff --git a/skills/translate-docs-zh/references/terminology.md b/skills/translate-docs-zh/references/terminology.md new file mode 100644 index 0000000000..00b4d38322 --- /dev/null +++ b/skills/translate-docs-zh/references/terminology.md @@ -0,0 +1,53 @@ +# Translation Terminology (zh-CN) + +This file defines preferred Chinese terminology for Apache Fory documentation translation. +Use these terms consistently across all translated docs. + +## Core Rules + +1. Prefer stable technical terms used in Chinese engineering docs. +2. Keep identifiers/protocol fields/type names in English when they are code symbols. +3. Do not translate terms in code blocks unless they are comments intended for readers. +4. If a term is ambiguous, choose the wording that matches protocol semantics, not product marketing wording. + +## Canonical Terms + +| English Term | Preferred Chinese | Notes | +| -------------------- | ----------------- | ----------------------------------------------------------------------------------------- | +| wire format | 编码格式 | Do not use `线协议` in this repo context. | +| serialization format | 序列化格式 | Use for data layout/encoding docs. | +| protocol | 协议 | Use only when discussing protocol semantics. | +| transport | 传输 | Use only for network transport context; do not replace encoding semantics with this term. | +| schema evolution | Schema 演进 | Keep `Schema` as-is in mixed technical headings when already used by repo style. | +| compatible mode | 兼容模式 | | +| type meta | 类型元信息 | | +| meta string | 元字符串 | | +| reference tracking | 引用跟踪 | | +| shared reference | 共享引用 | | +| circular reference | 循环引用 | | +| field tag ID | 字段 tag ID | Keep `tag ID` mixed for precision. | +| nullable | 可空 | | +| optional field | 可选字段 | | +| fixed-width | 定长 | | +| variable-width | 变长 | | +| little-endian | 小端序 | | +| big-endian | 大端序 | | +| offset | 偏移量 | | +| payload | 载荷 | | +| runtime | 运行时 | | +| codegen | 代码生成 | | +| cross-language | 跨语言 | | + +## Terms to Avoid (Unless User Explicitly Requests) + +| Avoid | Use Instead | Reason | +| -------------------------------------------- | --------------- | -------------------------------------------- | +| 线协议 | 编码格式 / 协议 | `线协议` is unnatural in this project style. | +| 传输格式 (for wire encoding semantics) | 编码格式 | Fory is not a transport framework. | +| 类定义元数据 (when referring to `type meta`) | 类型元信息 | Keep terminology short and consistent. | + +## Style Notes + +1. Keep product and library names in English (Apache Fory, Fory IDL, Protobuf, FlatBuffers). +2. Keep command flags and config keys in English (for example `--emit-fdl`, `enable_auto_type_id`). +3. In mixed headings, prefer repo-consistent forms (for example `Schema IDL`, `Compiler Guide` links can remain English anchor text if needed). diff --git a/src/pages/download/index.md b/src/pages/download/index.md index 39b7cd6bab..994d5b4192 100644 --- a/src/pages/download/index.md +++ b/src/pages/download/index.md @@ -11,8 +11,8 @@ For binary install, please see Apache Fory™ [install](/docs/start/install/) do The latest source release is 0.15.0: -| Version | Date | Source | Release Notes | -| ------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | +| Version | Date | Source | Release Notes | +| ------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | | 0.15.0 | 2026-02-10 | [source](https://www.apache.org/dyn/closer.lua/fory/0.15.0/apache-fory-0.15.0-src.tar.gz?action=download) [asc](https://downloads.apache.org/fory/0.15.0/apache-fory-0.15.0-src.tar.gz.asc) [sha512](https://downloads.apache.org/fory/0.15.0/apache-fory-0.15.0-src.tar.gz.sha512) | [release notes](https://github.com/apache/fory/releases/tag/v0.15.0) | ## All archived releases diff --git a/versioned_docs/version-0.13/introduction/overview.md b/versioned_docs/version-0.13/introduction/overview.md index e6715a2c7c..9d08ca0e31 100644 --- a/versioned_docs/version-0.13/introduction/overview.md +++ b/versioned_docs/version-0.13/introduction/overview.md @@ -55,12 +55,12 @@ Enterprise-grade security and compatibility: Apache Fory™ implements multiple binary protocols optimized for different scenarios: -| Protocol | Use Case | Key Features | -| ------------------------------------------------------------------------- | ------------------------------ | ------------------------------------------------------ | +| Protocol | Use Case | Key Features | +| ----------------------------------------------------------------------- | ------------------------------ | ------------------------------------------------------ | | **[Xlang Serialization](../specification/xlang_serialization_spec.md)** | Cross-language object exchange | Automatic serialization, references, polymorphism | | **[Java Serialization](../specification/java_serialization_spec.md)** | High-performance Java-only | Drop-in JDK serialization replacement, 100x faster | | **[Row Format](../specification/row_format_spec.md)** | Analytics and data processing | Zero-copy random access, Arrow compatibility | -| **Python Native** | Python-specific serialization | Pickle/cloudpickle replacement with better performance | +| **Python Native** | Python-specific serialization | Pickle/cloudpickle replacement with better performance | All protocols share the same optimized codebase, allowing improvements in one protocol to benefit others. @@ -68,21 +68,21 @@ All protocols share the same optimized codebase, allowing improvements in one pr ### User Guides -| Guide | Description | Source | Website | -| -------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | -| **Java Serialization** | Comprehensive guide for Java serialization | [java_serialization_guide.md](../guide/java_serialization_guide.md) | [📖 View](https://fory.apache.org/docs/guide/java_serialization) | +| Guide | Description | Source | Website | +| -------------------------------- | ------------------------------------------ | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| **Java Serialization** | Comprehensive guide for Java serialization | [java_serialization_guide.md](../guide/java_serialization_guide.md) | [📖 View](https://fory.apache.org/docs/guide/java_serialization) | | **Cross-Language Serialization** | Multi-language object exchange | [xlang_serialization_guide.md](../guide/xlang_serialization_guide.md) | [📖 View](https://fory.apache.org/docs/specification/fory_xlang_serialization_spec) | | **Row Format** | Zero-copy random access format | [row_format_guide.md](../guide/row_format_guide.md) | [📖 View](https://fory.apache.org/docs/specification/fory_row_format_spec) | -| **Python** | Python-specific features and usage | [python_guide.md](../guide/python_guide.md) | [📖 View](https://fory.apache.org/docs/guide/python_serialization) | -| **Rust** | Rust implementation and patterns | [rust_guide.md](../guide/rust_guide.md) | [📖 View](https://fory.apache.org/docs/guide/rust_serialization) | -| **Scala** | Scala integration and best practices | [scala_guide.md](../guide/scala_guide.md) | [📖 View](https://fory.apache.org/docs/guide/scala_serialization) | -| **GraalVM** | Native image support and AOT compilation | [graalvm_guide.md](../guide/graalvm_guide.md) | [📖 View](https://fory.apache.org/docs/guide/graalvm_serialization) | -| **Development** | Building and contributing to Fory | [DEVELOPMENT.md](../guide/DEVELOPMENT.md) | [📖 View](https://fory.apache.org/docs/guide/development) | +| **Python** | Python-specific features and usage | [python_guide.md](../guide/python_guide.md) | [📖 View](https://fory.apache.org/docs/guide/python_serialization) | +| **Rust** | Rust implementation and patterns | [rust_guide.md](../guide/rust_guide.md) | [📖 View](https://fory.apache.org/docs/guide/rust_serialization) | +| **Scala** | Scala integration and best practices | [scala_guide.md](../guide/scala_guide.md) | [📖 View](https://fory.apache.org/docs/guide/scala_serialization) | +| **GraalVM** | Native image support and AOT compilation | [graalvm_guide.md](../guide/graalvm_guide.md) | [📖 View](https://fory.apache.org/docs/guide/graalvm_serialization) | +| **Development** | Building and contributing to Fory | [DEVELOPMENT.md](../guide/DEVELOPMENT.md) | [📖 View](https://fory.apache.org/docs/guide/development) | ### Protocol Specifications -| Specification | Description | Source | Website | -| ----------------------- | ------------------------------ | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| Specification | Description | Source | Website | +| ----------------------- | ------------------------------ | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | | **Xlang Serialization** | Cross-language binary protocol | [xlang_serialization_spec.md](../specification/xlang_serialization_spec.md) | [📖 View](https://fory.apache.org/docs/specification/fory_xlang_serialization_spec) | | **Java Serialization** | Java-optimized protocol | [java_serialization_spec.md](../specification/java_serialization_spec.md) | [📖 View](https://fory.apache.org/docs/specification/fory_java_serialization_spec) | | **Row Format** | Row-based binary format | [row_format_spec.md](../specification/row_format_spec.md) | [📖 View](https://fory.apache.org/docs/specification/fory_row_format_spec) |