跳到主要内容
版本:1.4.0

Xlang 类型映射

说明:

  • 类型定义请参见规范中的类型系统
  • int16_t[n]/vector<T> 表示 int16_t[n]/vector<int16_t>
  • Xlang 序列化是 Java、Python、C++、Go、Rust、JavaScript/TypeScript、C#、Swift、Dart、 Scala 和 Kotlin 共享的可移植编码格式。所有对等实现的类型 ID、名称、Schema 和兼容性 设置必须保持一致。

用户类型 ID

注册用户类型(struct/ext/enum/union)时,内部类型 ID 以 8 位类型种类写入,用户类型 ID 则单独以无符号 varint32 写入。不进行位移或打包,user_type_id 的取值范围为 0~0xFFFFFFFE

示例:

用户 ID类型内部 ID编码后的用户 ID十进制
0STRUCT2700
0ENUM2500
1STRUCT2711
1COMPATIBLE_STRUCT2811
2NAMED_STRUCT2922

读取类型 ID 时:

  • 从类型 ID 字段读取内部类型 ID。
  • 如果内部类型是用户注册的类型种类,则以 varuint32 读取 user_type_id

类型映射

第一列列出 Fory Schema 表达式或规范编码标签。fixed int32tagged int64 等 标量编码行并不是 FDL 类型名称;在 FDL 中,它们由编码修饰符与具有语义的整数类型组合表示。

Fory Schema / 编码标签Fory 类型 IDJavaPythonJavaScript/TypeScriptC++GoRustC#SwiftDartScalaKotlin
bool1bool/BooleanboolBooleanboolboolboolboolBoolboolBooleanBoolean
int82byte/Byteint/pyfory.Int8Type.int8()int8_tint8i8sbyteInt8int + Int8TypeByteByte
int163short/Shortint/pyfory.Int16Type.int16()int16_tint16i16shortInt16int + Int16TypeShortShort
fixed int324int/Integerint/pyfory.FixedInt32Type.int32({ encoding: "fixed" })int32_tint32i32int + S.Fixed<S.Int32>Int32 + .fixedint + 定长元数据Int + 定长元数据@Fixed Int
int325int/Integerint/pyfory.Int32Type.int32()int32_tint32i32intInt32int + Int32TypeIntInt
fixed int646long/Longint/pyfory.FixedInt64Type.int64({ encoding: "fixed" })int64_tint64i64long + S.Fixed<S.Int64>Int64 + .fixedInt64 + 定长元数据Long + 定长元数据@Fixed Long
int647long/Longint/pyfory.Int64Type.int64()int64_tint64i64longInt64int / Int64LongLong
tagged int648long/Longint/pyfory.TaggedInt64Type.int64({ encoding: "tagged" })int64_tint64i64long + S.Tagged<S.Int64>Int64 + .taggedInt64 + tagged 元数据Long + tagged 元数据@Tagged Long
uint89short/Shortint/pyfory.UInt8Type.uint8()uint8_tuint8u8byteUInt8int + Uint8TypeInt + unsigned metadataUByte
uint1610int/Integerint/pyfory.UInt16Type.uint16()uint16_tuint16u16ushortUInt16int + Uint16TypeInt + unsigned metadataUShort
fixed uint3211long/Longint/pyfory.FixedUInt32Type.uint32({ encoding: "fixed" })uint32_tuint32u32uint + S.Fixed<S.UInt32>UInt32 + .fixedint + 定长 uint32 元数据Long + 定长无符号元数据@Fixed UInt
uint3212long/Longint/pyfory.UInt32Type.uint32()uint32_tuint32u32uintUInt32int + Uint32TypeLong + 无符号元数据UInt
fixed uint6413long/Longint/pyfory.FixedUInt64Type.uint64({ encoding: "fixed" })uint64_tuint64u64ulong + S.Fixed<S.UInt64>UInt64 + .fixedUint64 + 定长元数据Long + 定长无符号元数据@Fixed ULong
uint6414long/Longint/pyfory.UInt64Type.uint64()uint64_tuint64u64ulongUInt64Uint64Long + 无符号元数据ULong
tagged uint6415long/Longint/pyfory.TaggedUInt64Type.uint64({ encoding: "tagged" })uint64_tuint64u64ulong + S.Tagged<S.UInt64>UInt64 + .taggedUint64 + tagged 元数据Long + tagged 无符号元数据@Tagged ULong
float816///////////
float1617Float16原生 float / pyfory.Float16 注解numberfory::float16_tfloat16.Float16Float16HalfFloat16double + Float16TypeFloat16Float16
bfloat1618BFloat16原生 float / pyfory.BFloat16 注解numberfory::bfloat16_tbfloat16.BFloat16BFloat16BFloat16BFloat16double + Bfloat16TypeBFloat16BFloat16
float3219float/Floatfloat/pyfory.Float32Type.float32()floatfloat32f32floatFloatFloat32FloatFloat
float6420double/Doublefloat/pyfory.Float64Type.float64()doublefloat64f64doubleDoubledoubleDoubleDouble
string21StringstrStringstringstringString/strstringStringStringStringString
list22List/Collectionlist/tuplearrayvectorsliceVecList<T>[T]List<T>List[T]List<T>
set23Setset/setfory.SetSetHashSet<T>Set<T>Set<T>Set[T]Set<T>
map24MapdictMapunordered_mapmapHashMapDictionary<K,V>[K: V]Map<K, V>Map[K, V]Map<K, V>
enum25Enum 子类enum 子类/enum/enum[ForyEnum] enumenumenumScala 3 enumenum class
named_enum26Enum 子类enum 子类/enum/enum[ForyEnum] enumenumenumScala 3 enumenum class
struct27pojo/recorddata classobjectstruct/classstructstruct[ForyStruct] class/struct@ForyStruct struct/class@ForyStruct classcase class/classdata class/class
compatible_struct28pojo/recorddata classobjectstruct/classstructstruct[ForyStruct] class/struct@ForyStruct struct/class@ForyStruct classcase class/classdata class/class
named_struct29pojo/recorddata classobjectstruct/classstructstruct[ForyStruct] class/struct@ForyStruct struct/class@ForyStruct classcase class/classdata class/class
named_compatible_struct30pojo/recorddata classobjectstruct/classstructstruct[ForyStruct] class/struct@ForyStruct struct/class@ForyStruct classcase class/classdata class/class
ext31pojo/recorddata classobjectstruct/classstructstruct[ForyStruct] class/struct@ForyStruct struct/class@ForyStruct classcase class/classdata class/class
named_ext32pojo/recorddata classobjectstruct/classstructstruct[ForyStruct] class/struct@ForyStruct struct/class@ForyStruct classcase class/classdata class/class
union33Uniontyping.Union/std::variant<Ts...>/tagged union enum[ForyUnion] ADT recordtagged enum@ForyUnion classADT enumsealed class
none36nullNonenullstd::monostatenil()nullnilnullnullnull
duration37DurationtimedeltaNumberfory::DurationDurationDurationTimeSpanDurationDurationjava.time.Durationkotlin.time.Duration
timestamp38InstantdatetimeNumberfory::TimestampTimeTimestampDateTime/DateTimeOffsetDateTimestampjava.time.Instantjava.time.Instant
date39LocalDatedatetime.dateDatefory::Datefory.DateDateDateOnlyLocalDateLocalDatejava.time.LocalDatejava.time.LocalDate
decimal40BigDecimalDecimalDecimalfory::serialization::Decimalfory.Decimalfory::DecimaldecimalDecimalDecimaljava.math.BigDecimaljava.math.BigDecimal
binary41byte[]bytes/uint8_t[n]/vector<T>[n]uint8/[]TVec<u8>byte[]DataUint8ListArray[Byte]ByteArray
array<bool> (bool_array)43bool[]BoolArray / ndarray(np.bool_)BoolArray / Type.boolArray()bool[n][n]bool/[]TVec<bool>bool[][Bool] + @ArrayFieldBoolListArray[Boolean]BooleanArray
array<int8> (int8_array)44@Int8Type byte[]Int8Array / ndarray(int8)Type.int8Array()int8_t[n]/vector<T>[n]int8/[]TVec<i8>sbyte[][Int8] + @ArrayFieldInt8ListArray[Byte] + 元数据ByteArray + @ArrayType
array<int16> (int16_array)45short[]Int16Array / ndarray(int16)Type.int16Array()int16_t[n]/vector<T>[n]int16/[]TVec<i16>short[][Int16] + @ArrayFieldInt16ListArray[Short]ShortArray
array<int32> (int32_array)46int[]Int32Array / ndarray(int32)Type.int32Array()int32_t[n]/vector<T>[n]int32/[]TVec<i32>int[][Int32] + @ArrayFieldInt32ListArray[Int]IntArray
array<int64> (int64_array)47long[]Int64Array / ndarray(int64)Type.int64Array()int64_t[n]/vector<T>[n]int64/[]TVec<i64>long[][Int64] + @ArrayFieldInt64ListArray[Long]LongArray
array<uint8> (uint8_array)48@UInt8Type byte[]UInt8Array / ndarray(uint8)Type.uint8Array()uint8_t[n]/vector<T>[n]uint8/[]TVec<u8>byte[][UInt8] + @ArrayFieldUint8ListArray[Byte] + 元数据UByteArray
array<uint16> (uint16_array)49@UInt16Type short[]UInt16Array / ndarray(uint16)Type.uint16Array()uint16_t[n]/vector<T>[n]uint16/[]TVec<u16>ushort[][UInt16] + @ArrayFieldUint16ListArray[Short] + 元数据UShortArray
array<uint32> (uint32_array)50@UInt32Type int[]UInt32Array / ndarray(uint32)Type.uint32Array()uint32_t[n]/vector<T>[n]uint32/[]TVec<u32>uint[][UInt32] + @ArrayFieldUint32ListArray[Int] + 元数据UIntArray
array<uint64> (uint64_array)51@UInt64Type long[]UInt64Array / ndarray(uint64)Type.uint64Array()uint64_t[n]/vector<T>[n]uint64/[]TVec<u64>ulong[][UInt64] + @ArrayFieldUint64ListArray[Long] + 元数据ULongArray
array<float8> (float8_array)52///////////
array<float16> (float16_array)53Float16Array / @Float16Type short[]Float16Array / ndarray(float16)Float16Array / Type.float16Array()fory::float16_t[n]/std::vector<fory::float16_t>[N]float16.Float16 / []float16.Float16Vec<Float16> / [Float16; N]Half[] / S.Array<S.Float16>[Float16] + @ArrayFieldFloat16ListArray[Short] + 元数据Float16Array
array<bfloat16> (bfloat16_array)54BFloat16Array / @BFloat16Type short[]BFloat16Array / ndarray(bfloat16)BFloat16Array / Type.bfloat16Array()fory::bfloat16_t[n]/std::vector<fory::bfloat16_t>[N]bfloat16.BFloat16 / []bfloat16.BFloat16Vec<BFloat16> / [BFloat16; N]BFloat16[] / S.Array<S.BFloat16>[BFloat16] + @ArrayFieldBfloat16ListArray[Short] + 元数据BFloat16Array
array<float32> (float32_array)55float[]Float32Array / ndarray(float32)Type.float32Array()float[n]/vector<T>[n]float32/[]TVec<f32>float[][Float] + @ArrayFieldFloat32ListArray[Float]FloatArray
array<float64> (float64_array)56double[]Float64Array / ndarray(float64)Type.float64Array()double[n]/vector<T>[n]float64/[]TVec<f64>double[][Double] + @ArrayFieldFloat64ListArray[Double]DoubleArray

说明:

  • Python 的 pyfory.Float16pyfory.BFloat16 是保留的注解标记;标量值反序列化为 Python 原生 float
  • Python 的 BoolArrayInt8ArrayInt16ArrayInt32ArrayInt64ArrayUInt8ArrayUInt16ArrayUInt32ArrayUInt64ArrayFloat16ArrayBFloat16ArrayFloat32ArrayFloat64Array 是公开的稠密数组封装,提供类似列表的序列行为。
  • JavaScript 的 BoolArray、回退实现 Float16ArrayBFloat16Array 是由 Uint8ArrayUint16Array 支持的公开稠密数组封装。标量 float16bfloat16 值使用 number。原生支持 Float16Array 的 JavaScript 环境可能会为 array<float16> 返回该原生载体。
  • Java 中普通的 byte[] 映射到 binary。数值字节数组使用类型使用位置注解: array<int8> 使用 @Int8Type byte[]array<uint8> 使用 @UInt8Type byte[]
  • Dart 对标量 float16bfloat16 使用 double,并分别附加 Float16TypeBfloat16Type 元数据;array<bool> 使用 BoolList;整数、float32 和 float64 数组使用 typed-data 列表;array<float16>array<bfloat16> 分别使用 Float16ListBfloat16List。普通 Dart List<bool> 映射到 list<bool>;但如果字段使用 @ArrayField(element: BoolType()),或使用 @ForyField(type: ArrayType(element: BoolType())) 并以 BoolList 为载体,则不适用此默认映射。
  • 在 xlang 模式下,Float16[]BFloat16[] 仍是对象数组,并使用 list 编码类型进行序列化。
  • ARRAY (42) 保留给未来专用的多维数组编码,不属于当前 xlang 类型映射范围。
  • 当前 xlang 对一维基本类型数组使用 *_ARRAY,对多维数组使用嵌套的 list
  • 在生成的 Schema 和动态 std::any 值中,C++ xlang 的 datetimestampduration 分别映射到 fory::Datefory::Timestampfory::Durationstd::chrono 时间类型 只能作为显式的 C++ 序列化和反序列化目标。
  • Kotlin KSP xlang 将 UByteUShortUIntULong 分别映射到 uint8uint16uint32uint64。Kotlin 基本类型和无符号数组载体映射到稠密数组。 ByteArray 默认映射到 binary;当其类型使用位置通过 Fory ArrayType 标记时,则映射到 array<int8>array<float16>array<bfloat16> 使用 Java 核心库的 Float16ArrayBFloat16Array
  • Kotlin xlang 的 duration 使用 kotlin.time.Duration。xlang duration 载荷无法表示无穷值, 遇到无穷值时必须抛出序列化错误。
  • list<T>array<T> 是不同的 Schema 种类。仅在兼容模式的 struct/class 字段匹配中, 当 T 属于稠密布尔或数值数组域时,顶层直接字段 list<T> 可以读取为顶层直接字段 array<T>,反向也同样允许。具有相同符号性和位宽的整数列表元素编码,与对应的稠密数组 元素域相匹配。该规则不适用于嵌套的 collection、map、array、union 或泛型位置。对等端的 list<T?> 元素 Schema 仍可与本地 array<T> 字段兼容匹配;如果实际载荷包含 null 元素, 稠密数组读取器会抛出兼容读取错误,而不是强制转换该值。列表元素的引用跟踪帧结构与元素 Schema 是否可空相互独立;当本地匹配字段为 array<T>,而运行时无法在不经过泛型或引用 路径的情况下将其具体化时,兼容字段分类可能会拒绝这种引用跟踪帧结构。
  • binaryarray<uint8> 是不同的 Schema 种类。仅在兼容模式的 struct/class 字段匹配中, 顶层直接字段 binary 可以读取为顶层直接字段 array<uint8>,反向也可以读取为相同的字节序列。 该规则不适用于嵌套的 collection、map、array、union 或泛型位置,也不包括 array<int8>
  • 上表是规范的 xlang Schema 映射。在兼容模式的 struct/class 字段匹配中,兼容读取器可以应用 xlang_serialization_spec.md 定义的标量字段适配规则。这些规则不会改变 TypeDef 元数据、动态根 类型映射、同 Schema 模式,也不适用于嵌套的 collection、map、array、union 或泛型位置。

Scala IDL 映射

Scala Schema IDL 目标仅生成 Scala 3 源代码。fory-scala 构件仍会同时为 Scala 2.13 和 Scala 3 进行交叉构建。

Fory Schema 种类Scala 生成载体
optional TOption[T]
boolBoolean
int8, int16, int32, int64Byte, Short, Int, Long
uint8, uint16, uint32, uint64IntIntLongLong,并附加 Fory 无符号类型元数据
float16, bfloat16JVM Float16BFloat16 载体
float32, float64Float, Double
stringString
binaryArray[Byte]
list<T>, set<T>, map<K, V>List[T], Set[T], Map[K, V]
array<bool>Array[Boolean]
array<int8>, array<uint8>带有有符号/无符号描述符元数据的 Array[Byte]
array<int16>, array<uint16>带有有符号/无符号描述符元数据的 Array[Short]
array<int32>, array<uint32>带有有符号/无符号描述符元数据的 Array[Int]
array<int64>, array<uint64>带有有符号/无符号描述符元数据的 Array[Long]
array<float16>, array<bfloat16>带有低精度描述符元数据的 Array[Short]
array<float32>, array<float64>Array[Float], Array[Double]
date, timestamp, durationjava.time.LocalDate, java.time.Instant, java.time.Duration
decimaljava.math.BigDecimal
message默认生成 Scala 3 case class;仅在 message/union 构造循环中使用普通 class
enumScala 3 enum,通过 case 级 @ForyEnumId 注解提供稳定的 Fory 枚举 ID
unionScala 3 ADT enum derives ForySerializer
anyAnyRef

生成的 Scala 描述符元数据由 Scala 3 宏基于 Scala 编译期类型推导得出,其中包括嵌套泛型、 Option、数组、标量编码注解、可空性和 @Ref。Java 反射并不是生成 Scala TypeDef 元数据的 事实来源。Scala 的 @Ref 元数据由共享注解 org.apache.fory.annotation.Ref 表示;@Ref 是 JVM 引用跟踪元数据的所有者。

类型信息

由于各语言的类型系统存在差异,这些类型无法在语言之间一一映射。

如果一种宿主语言类型对应多种 Fory 标量编码,例如 Java long 可以表示定长、varint 或 tagged int64,当默认编码并非预期 Schema 时,用户必须提供编码元数据。

类型注解

当类型作为另一个类的字段时,用户可以为该类型的字段或整个类型提供元数据提示。 其他语言也可以提供这类信息:

  • Java:使用注解。
  • C++:使用宏和模板。
  • Go:使用 struct tag。
  • Python:使用类型提示。
  • Rust:使用宏。

示例:

  • Java:

    class Foo {
    private @Int32Type int f1;
    private List<@Int32Type Integer> f2;
    }
  • Python:

    class Foo:
    f1: pyfory.Int32
    f2: List[pyfory.Int32]