This is an automated email from the ASF dual-hosted git repository. chaokunyang pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/fory-site.git
commit 195b5d6d4f8339b2c985856c2827f9eae49f01d0 Author: chaokunyang <[email protected]> AuthorDate: Sat May 23 08:56:01 2026 +0000 π synced local 'docs/specification/' with remote 'docs/specification/' --- docs/specification/xlang_serialization_spec.md | 3 +- docs/specification/xlang_type_mapping.md | 114 +++++++++++++------------ 2 files changed, 60 insertions(+), 57 deletions(-) diff --git a/docs/specification/xlang_serialization_spec.md b/docs/specification/xlang_serialization_spec.md index 6e1784b402..2c7e16cd0d 100644 --- a/docs/specification/xlang_serialization_spec.md +++ b/docs/specification/xlang_serialization_spec.md @@ -26,7 +26,8 @@ Apache Foryβ’ xlang serialization enables automatic cross-language object seria Key characteristics: - **Automatic**: No IDL definition, no schema compilation, no manual object-to-protocol conversion -- **Cross-language**: Same binary format works seamlessly across Java, Python, C++, Rust, Go, JavaScript, and more +- **Cross-language**: Same binary format works across Java, Python, C++, Go, + Rust, JavaScript/TypeScript, C#, Swift, Dart, Scala, and Kotlin - **Reference-aware**: Handles shared references and circular references without duplication or infinite recursion - **Polymorphic**: Supports object polymorphism with runtime type resolution diff --git a/docs/specification/xlang_type_mapping.md b/docs/specification/xlang_type_mapping.md index 8dd242c202..a50c64261c 100644 --- a/docs/specification/xlang_type_mapping.md +++ b/docs/specification/xlang_type_mapping.md @@ -23,7 +23,9 @@ Note: - For type definition, see [Type Systems in Spec](xlang_serialization_spec.md#type-systems) - `int16_t[n]/vector<T>` indicates `int16_t[n]/vector<int16_t>` -- The cross-language serialization is not stable, do not use it in your production environment. +- Xlang serialization is the portable wire format shared by Java, Python, C++, + Go, Rust, JavaScript/TypeScript, C#, Swift, Dart, Scala, and Kotlin. Keep type + IDs, names, schemas, and compatibility settings aligned across every peer. ## User Type IDs @@ -52,61 +54,61 @@ The first column names the Fory schema expression or canonical wire tag. Scalar encoding rows such as `fixed int32` and `tagged int64` are not FDL type names; FDL spells them as an encoding modifier plus a semantic integer type. -| Fory schema / wire tag | Fory Type ID | Java | Python | Javascript | C++ | Golang | Rust | -| ---------------------------------- | ------------ | ----------------------------------------- | ----------------------------------------- | ------------------------------------- | --------------------------------------------------- | ---------------------------------------------- | --------------------------------- | -| bool | 1 | bool/Boolean | bool | Boolean | bool | bool | bool | -| int8 | 2 | byte/Byte | int/pyfory.Int8 | Type.int8() | int8_t | int8 | i8 | -| int16 | 3 | short/Short | int/pyfory.Int16 | Type.int16() | int16_t | int16 | i16 | -| fixed int32 | 4 | int/Integer | int/pyfory.FixedInt32 | `Type.int32({ encoding: "fixed" })` | int32_t | int32 | i32 | -| int32 | 5 | int/Integer | int/pyfory.Int32 | Type.int32() | int32_t | int32 | i32 | -| fixed int64 | 6 | long/Long | int/pyfory.FixedInt64 | `Type.int64({ encoding: "fixed" })` | int64_t | int64 | i64 | -| int64 | 7 | long/Long | int/pyfory.Int64 | Type.int64() | int64_t | int64 | i64 | -| tagged int64 | 8 | long/Long | int/pyfory.TaggedInt64 | `Type.int64({ encoding: "tagged" })` | int64_t | int64 | i64 | -| uint8 | 9 | short/Short | int/pyfory.UInt8 | Type.uint8() | uint8_t | uint8 | u8 | -| uint16 | 10 | int/Integer | int/pyfory.UInt16 | Type.uint16() | uint16_t | uint16 | u16 | -| fixed uint32 | 11 | long/Long | int/pyfory.FixedUInt32 | `Type.uint32({ encoding: "fixed" })` | uint32_t | uint32 | u32 | -| uint32 | 12 | long/Long | int/pyfory.UInt32 | Type.uint32() | uint32_t | uint32 | u32 | -| fixed uint64 | 13 | long/Long | int/pyfory.FixedUInt64 | `Type.uint64({ encoding: "fixed" })` | uint64_t | uint64 | u64 | -| uint64 | 14 | long/Long | int/pyfory.UInt64 | Type.uint64() | uint64_t | uint64 | u64 | -| tagged uint64 | 15 | long/Long | int/pyfory.TaggedUInt64 | `Type.uint64({ encoding: "tagged" })` | uint64_t | uint64 | u64 | -| float8 | 16 | / | / | / | / | / | / | -| float16 | 17 | Float16 | native float / pyfory.Float16 annotation | `number` | `fory::float16_t` | `float16.Float16` | `Float16` | -| bfloat16 | 18 | BFloat16 | native float / pyfory.BFloat16 annotation | `number` | `fory::bfloat16_t` | `bfloat16.BFloat16` | `BFloat16` | -| float32 | 19 | float/Float | float/pyfory.Float32 | Type.float32() | float | float32 | f32 | -| float64 | 20 | double/Double | float/pyfory.Float64 | Type.float64() | double | float64 | f64 | -| string | 21 | String | str | String | string | string | String/str | -| list | 22 | List/Collection | list/tuple | array | vector | slice | Vec | -| set | 23 | Set | set | / | set | fory.Set | Set | -| map | 24 | Map | dict | Map | unordered_map | map | HashMap | -| enum | 25 | Enum subclasses | enum subclasses | / | enum | / | enum | -| named_enum | 26 | Enum subclasses | enum subclasses | / | enum | / | enum | -| struct | 27 | pojo/record | data class | object | struct/class | struct | struct | -| compatible_struct | 28 | pojo/record | data class | object | struct/class | struct | struct | -| named_struct | 29 | pojo/record | data class | object | struct/class | struct | struct | -| named_compatible_struct | 30 | pojo/record | data class | object | struct/class | struct | struct | -| ext | 31 | pojo/record | data class | object | struct/class | struct | struct | -| named_ext | 32 | pojo/record | data class | object | struct/class | struct | struct | -| union | 33 | Union | typing.Union | / | `std::variant<Ts...>` | / | tagged union enum | -| none | 36 | null | None | null | `std::monostate` | nil | `()` | -| duration | 37 | Duration | timedelta | Number | duration | Duration | Duration | -| timestamp | 38 | Instant | datetime | Number | std::chrono::nanoseconds | Time | Timestamp | -| date | 39 | LocalDate | datetime.date | Date | fory::serialization::Date | fory.Date | Date | -| decimal | 40 | BigDecimal | Decimal | Decimal | / | fory.Decimal | fory::Decimal | -| binary | 41 | byte[] | bytes | / | `uint8_t[n]/vector<T>` | `[n]uint8/[]T` | `Vec<u8>` | -| `array<bool>` (bool_array) | 43 | bool[] | BoolArray / ndarray(np.bool\_) | BoolArray / Type.boolArray() | `bool[n]` | `[n]bool/[]T` | `Vec<bool>` | -| `array<int8>` (int8_array) | 44 | `@Int8Type byte[]` | Int8Array / ndarray(int8) | Type.int8Array() | `int8_t[n]/vector<T>` | `[n]int8/[]T` | `Vec<i8>` | -| `array<int16>` (int16_array) | 45 | short[] | Int16Array / ndarray(int16) | Type.int16Array() | `int16_t[n]/vector<T>` | `[n]int16/[]T` | `Vec<i16>` | -| `array<int32>` (int32_array) | 46 | int[] | Int32Array / ndarray(int32) | Type.int32Array() | `int32_t[n]/vector<T>` | `[n]int32/[]T` | `Vec<i32>` | -| `array<int64>` (int64_array) | 47 | long[] | Int64Array / ndarray(int64) | Type.int64Array() | `int64_t[n]/vector<T>` | `[n]int64/[]T` | `Vec<i64>` | -| `array<uint8>` (uint8_array) | 48 | `@UInt8Type byte[]` | UInt8Array / ndarray(uint8) | Type.uint8Array() | `uint8_t[n]/vector<T>` | `[n]uint8/[]T` | `Vec<u8>` | -| `array<uint16>` (uint16_array) | 49 | `@UInt16Type short[]` | UInt16Array / ndarray(uint16) | Type.uint16Array() | `uint16_t[n]/vector<T>` | `[n]uint16/[]T` | `Vec<u16>` | -| `array<uint32>` (uint32_array) | 50 | `@UInt32Type int[]` | UInt32Array / ndarray(uint32) | Type.uint32Array() | `uint32_t[n]/vector<T>` | `[n]uint32/[]T` | `Vec<u32>` | -| `array<uint64>` (uint64_array) | 51 | `@UInt64Type long[]` | UInt64Array / ndarray(uint64) | Type.uint64Array() | `uint64_t[n]/vector<T>` | `[n]uint64/[]T` | `Vec<u64>` | -| `array<float8>` (float8_array) | 52 | / | / | / | / | / | / | -| `array<float16>` (float16_array) | 53 | `Float16Array` / `@Float16Type short[]` | Float16Array / ndarray(float16) | Float16Array / Type.float16Array() | `fory::float16_t[n]/std::vector<fory::float16_t>` | `[N]float16.Float16` / `[]float16.Float16` | `Vec<Float16>` / `[Float16; N]` | -| `array<bfloat16>` (bfloat16_array) | 54 | `BFloat16Array` / `@BFloat16Type short[]` | BFloat16Array / ndarray(bfloat16) | BFloat16Array / Type.bfloat16Array() | `fory::bfloat16_t[n]/std::vector<fory::bfloat16_t>` | `[N]bfloat16.BFloat16` / `[]bfloat16.BFloat16` | `Vec<BFloat16>` / `[BFloat16; N]` | -| `array<float32>` (float32_array) | 55 | float[] | Float32Array / ndarray(float32) | Type.float32Array() | `float[n]/vector<T>` | `[n]float32/[]T` | `Vec<f32>` | -| `array<float64>` (float64_array) | 56 | double[] | Float64Array / ndarray(float64) | Type.float64Array() | `double[n]/vector<T>` | `[n]float64/[]T` | `Vec<f64>` | +| Fory schema / wire tag | Fory Type ID | Java | Python | JavaScript/TypeScript | C++ | Go | Rust | C# | Swift | Dart | Scala | Kotlin | +| ---------------------------------- | ------------ | ----------------------------------------- | ----------------------------------------- | ------------------------------------- | --------------------------------------------------- | ---------------------------------------------- | --------------------------------- | -------------------------------- | ------------------------ | --------------------------- | ------------------------------- | ---------------------- | +| bool | 1 | bool/Boolean | bool | Boolean | bool | bool | bool | bool | Bool | bool | Boolean | Boolean | +| int8 | 2 | byte/Byte | int/pyfory.Int8 | Type.int8() | int8_t | int8 | i8 | sbyte | Int8 | int + `Int8Type` | Byte | Byte | +| int16 | 3 | short/Short | int/pyfory.Int16 | Type.int16() | int16_t | int16 | i16 | short | Int16 | int + `Int16Type` | Short | Short | +| fixed int32 | 4 | int/Integer | int/pyfory.FixedInt32 | `Type.int32({ encoding: "fixed" })` | int32_t | int32 | i32 | int + `S.Fixed<S.Int32>` | Int32 + `.fixed` | int + fixed metadata | Int + fixed metadata | `@Fixed Int` | +| int32 | 5 | int/Integer | int/pyfory.Int32 | Type.int32() | int32_t | int32 | i32 | int | Int32 | int + `Int32Type` | Int | Int | +| fixed int64 | 6 | long/Long | int/pyfory.FixedInt64 | `Type.int64({ encoding: "fixed" })` | int64_t | int64 | i64 | long + `S.Fixed<S.Int64>` | Int64 + `.fixed` | Int64 + fixed metadata | Long + fixed metadata | `@Fixed Long` | +| int64 | 7 | long/Long | int/pyfory.Int64 | Type.int64() | int64_t | int64 | i64 | long | Int64 | int / Int64 | Long | Long | +| tagged int64 | 8 | long/Long | int/pyfory.TaggedInt64 | `Type.int64({ encoding: "tagged" })` | int64_t | int64 | i64 | long + `S.Tagged<S.Int64>` | Int64 + `.tagged` | Int64 + tagged metadata | Long + tagged metadata | `@Tagged Long` | +| uint8 | 9 | short/Short | int/pyfory.UInt8 | Type.uint8() | uint8_t | uint8 | u8 | byte | UInt8 | int + `Uint8Type` | Int + unsigned metadata | UByte | +| uint16 | 10 | int/Integer | int/pyfory.UInt16 | Type.uint16() | uint16_t | uint16 | u16 | ushort | UInt16 | int + `Uint16Type` | Int + unsigned metadata | UShort | +| fixed uint32 | 11 | long/Long | int/pyfory.FixedUInt32 | `Type.uint32({ encoding: "fixed" })` | uint32_t | uint32 | u32 | uint + `S.Fixed<S.UInt32>` | UInt32 + `.fixed` | int + fixed uint32 metadata | Long + fixed unsigned metadata | `@Fixed UInt` | +| uint32 | 12 | long/Long | int/pyfory.UInt32 | Type.uint32() | uint32_t | uint32 | u32 | uint | UInt32 | int + `Uint32Type` | Long + unsigned metadata | UInt | +| fixed uint64 | 13 | long/Long | int/pyfory.FixedUInt64 | `Type.uint64({ encoding: "fixed" })` | uint64_t | uint64 | u64 | ulong + `S.Fixed<S.UInt64>` | UInt64 + `.fixed` | Uint64 + fixed metadata | Long + fixed unsigned metadata | `@Fixed ULong` | +| uint64 | 14 | long/Long | int/pyfory.UInt64 | Type.uint64() | uint64_t | uint64 | u64 | ulong | UInt64 | Uint64 | Long + unsigned metadata | ULong | +| tagged uint64 | 15 | long/Long | int/pyfory.TaggedUInt64 | `Type.uint64({ encoding: "tagged" })` | uint64_t | uint64 | u64 | ulong + `S.Tagged<S.UInt64>` | UInt64 + `.tagged` | Uint64 + tagged metadata | Long + tagged unsigned metadata | `@Tagged ULong` | +| float8 | 16 | / | / | / | / | / | / | / | / | / | / | / | +| float16 | 17 | Float16 | native float / pyfory.Float16 annotation | `number` | `fory::float16_t` | `float16.Float16` | `Float16` | Half | Float16 | double + `Float16Type` | Float16 | Float16 | +| bfloat16 | 18 | BFloat16 | native float / pyfory.BFloat16 annotation | `number` | `fory::bfloat16_t` | `bfloat16.BFloat16` | `BFloat16` | BFloat16 | BFloat16 | double + `Bfloat16Type` | BFloat16 | BFloat16 | +| float32 | 19 | float/Float | float/pyfory.Float32 | Type.float32() | float | float32 | f32 | float | Float | Float32 | Float | Float | +| float64 | 20 | double/Double | float/pyfory.Float64 | Type.float64() | double | float64 | f64 | double | Double | double | Double | Double | +| string | 21 | String | str | String | string | string | String/str | string | String | String | String | String | +| list | 22 | List/Collection | list/tuple | array | vector | slice | Vec | List<T> | [T] | List<T> | List[T] | List<T> | +| set | 23 | Set | set | / | set | fory.Set | Set | HashSet<T> | Set<T> | Set<T> | Set[T] | Set<T> | +| map | 24 | Map | dict | Map | unordered_map | map | HashMap | Dictionary<K,V> | [K: V] | Map<K, V> | Map[K, V] | Map<K, V> | +| enum | 25 | Enum subclasses | enum subclasses | / | enum | / | enum | enum | enum | enum | Scala 3 enum | enum class | +| named_enum | 26 | Enum subclasses | enum subclasses | / | enum | / | enum | enum | enum | enum | Scala 3 enum | enum class | +| struct | 27 | pojo/record | data class | object | struct/class | struct | struct | [ForyObject] class/struct | @ForyStruct struct/class | @ForyStruct class | case class/class | data class/class | +| compatible_struct | 28 | pojo/record | data class | object | struct/class | struct | struct | [ForyObject] class/struct | @ForyStruct struct/class | @ForyStruct class | case class/class | data class/class | +| named_struct | 29 | pojo/record | data class | object | struct/class | struct | struct | [ForyObject] class/struct | @ForyStruct struct/class | @ForyStruct class | case class/class | data class/class | +| named_compatible_struct | 30 | pojo/record | data class | object | struct/class | struct | struct | [ForyObject] class/struct | @ForyStruct struct/class | @ForyStruct class | case class/class | data class/class | +| ext | 31 | pojo/record | data class | object | struct/class | struct | struct | [ForyObject] class/struct | @ForyStruct struct/class | @ForyStruct class | case class/class | data class/class | +| named_ext | 32 | pojo/record | data class | object | struct/class | struct | struct | [ForyObject] class/struct | @ForyStruct struct/class | @ForyStruct class | case class/class | data class/class | +| union | 33 | Union | typing.Union | / | `std::variant<Ts...>` | / | tagged union enum | Union subclass | tagged enum | @ForyUnion class | ADT enum | sealed class | +| none | 36 | null | None | null | `std::monostate` | nil | `()` | null | nil | null | null | null | +| duration | 37 | Duration | timedelta | Number | duration | Duration | Duration | TimeSpan | Duration | Duration | java.time.Duration | kotlin.time.Duration | +| timestamp | 38 | Instant | datetime | Number | std::chrono::nanoseconds | Time | Timestamp | DateTime/DateTimeOffset | Date | Timestamp | java.time.Instant | java.time.Instant | +| date | 39 | LocalDate | datetime.date | Date | fory::serialization::Date | fory.Date | Date | DateOnly | LocalDate | LocalDate | java.time.LocalDate | java.time.LocalDate | +| decimal | 40 | BigDecimal | Decimal | Decimal | / | fory.Decimal | fory::Decimal | decimal | Decimal | Decimal | java.math.BigDecimal | java.math.BigDecimal | +| binary | 41 | byte[] | bytes | / | `uint8_t[n]/vector<T>` | `[n]uint8/[]T` | `Vec<u8>` | byte[] | Data | Uint8List | Array[Byte] | ByteArray | +| `array<bool>` (bool_array) | 43 | bool[] | BoolArray / ndarray(np.bool\_) | BoolArray / Type.boolArray() | `bool[n]` | `[n]bool/[]T` | `Vec<bool>` | bool[] | [Bool] + @ArrayField | BoolList | Array[Boolean] | BooleanArray | +| `array<int8>` (int8_array) | 44 | `@Int8Type byte[]` | Int8Array / ndarray(int8) | Type.int8Array() | `int8_t[n]/vector<T>` | `[n]int8/[]T` | `Vec<i8>` | sbyte[] | [Int8] + @ArrayField | Int8List | Array[Byte] + metadata | ByteArray + @ArrayType | +| `array<int16>` (int16_array) | 45 | short[] | Int16Array / ndarray(int16) | Type.int16Array() | `int16_t[n]/vector<T>` | `[n]int16/[]T` | `Vec<i16>` | short[] | [Int16] + @ArrayField | Int16List | Array[Short] | ShortArray | +| `array<int32>` (int32_array) | 46 | int[] | Int32Array / ndarray(int32) | Type.int32Array() | `int32_t[n]/vector<T>` | `[n]int32/[]T` | `Vec<i32>` | int[] | [Int32] + @ArrayField | Int32List | Array[Int] | IntArray | +| `array<int64>` (int64_array) | 47 | long[] | Int64Array / ndarray(int64) | Type.int64Array() | `int64_t[n]/vector<T>` | `[n]int64/[]T` | `Vec<i64>` | long[] | [Int64] + @ArrayField | Int64List | Array[Long] | LongArray | +| `array<uint8>` (uint8_array) | 48 | `@UInt8Type byte[]` | UInt8Array / ndarray(uint8) | Type.uint8Array() | `uint8_t[n]/vector<T>` | `[n]uint8/[]T` | `Vec<u8>` | byte[] | [UInt8] + @ArrayField | Uint8List | Array[Byte] + metadata | UByteArray | +| `array<uint16>` (uint16_array) | 49 | `@UInt16Type short[]` | UInt16Array / ndarray(uint16) | Type.uint16Array() | `uint16_t[n]/vector<T>` | `[n]uint16/[]T` | `Vec<u16>` | ushort[] | [UInt16] + @ArrayField | Uint16List | Array[Short] + metadata | UShortArray | +| `array<uint32>` (uint32_array) | 50 | `@UInt32Type int[]` | UInt32Array / ndarray(uint32) | Type.uint32Array() | `uint32_t[n]/vector<T>` | `[n]uint32/[]T` | `Vec<u32>` | uint[] | [UInt32] + @ArrayField | Uint32List | Array[Int] + metadata | UIntArray | +| `array<uint64>` (uint64_array) | 51 | `@UInt64Type long[]` | UInt64Array / ndarray(uint64) | Type.uint64Array() | `uint64_t[n]/vector<T>` | `[n]uint64/[]T` | `Vec<u64>` | ulong[] | [UInt64] + @ArrayField | Uint64List | Array[Long] + metadata | ULongArray | +| `array<float8>` (float8_array) | 52 | / | / | / | / | / | / | / | / | / | / | / | +| `array<float16>` (float16_array) | 53 | `Float16Array` / `@Float16Type short[]` | Float16Array / ndarray(float16) | Float16Array / Type.float16Array() | `fory::float16_t[n]/std::vector<fory::float16_t>` | `[N]float16.Float16` / `[]float16.Float16` | `Vec<Float16>` / `[Float16; N]` | Half[] / S.Array<S.Float16> | [Float16] + @ArrayField | Float16List | Array[Short] + metadata | Float16Array | +| `array<bfloat16>` (bfloat16_array) | 54 | `BFloat16Array` / `@BFloat16Type short[]` | BFloat16Array / ndarray(bfloat16) | BFloat16Array / Type.bfloat16Array() | `fory::bfloat16_t[n]/std::vector<fory::bfloat16_t>` | `[N]bfloat16.BFloat16` / `[]bfloat16.BFloat16` | `Vec<BFloat16>` / `[BFloat16; N]` | BFloat16[] / S.Array<S.BFloat16> | [BFloat16] + @ArrayField | Bfloat16List | Array[Short] + metadata | BFloat16Array | +| `array<float32>` (float32_array) | 55 | float[] | Float32Array / ndarray(float32) | Type.float32Array() | `float[n]/vector<T>` | `[n]float32/[]T` | `Vec<f32>` | float[] | [Float] + @ArrayField | Float32List | Array[Float] | FloatArray | +| `array<float64>` (float64_array) | 56 | double[] | Float64Array / ndarray(float64) | Type.float64Array() | `double[n]/vector<T>` | `[n]float64/[]T` | `Vec<f64>` | double[] | [Double] + @ArrayField | Float64List | Array[Double] | DoubleArray | Notes: --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
