Skip to main content
Version: dev

Xlang Type Mapping

Note:

  • For type definition, see Type Systems in Spec
  • 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.

User Type IDs

When registering user types (struct/ext/enum/union), the internal type ID is written as the 8-bit kind, and the user type ID is written separately as an unsigned varint32. There is no bit shift/packing, and user_type_id can be in the range 0~0xFFFFFFFE.

Examples:

User IDTypeInternal IDEncoded User IDDecimal
0STRUCT2700
0ENUM2500
1STRUCT2711
1COMPATIBLE_STRUCT2811
2NAMED_STRUCT2922

When reading type IDs:

  • Read internal type ID from the type ID field.
  • If the internal type is a user-registered kind, read user_type_id as varuint32.

Type Mapping

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 tagFory Type IDJavaPythonJavascriptC++GolangRust
bool1bool/BooleanboolBooleanboolboolbool
int82byte/Byteint/pyfory.Int8Type.int8()int8_tint8i8
int163short/Shortint/pyfory.Int16Type.int16()int16_tint16i16
fixed int324int/Integerint/pyfory.FixedInt32Type.int32({ encoding: "fixed" })int32_tint32i32
int325int/Integerint/pyfory.Int32Type.int32()int32_tint32i32
fixed int646long/Longint/pyfory.FixedInt64Type.int64({ encoding: "fixed" })int64_tint64i64
int647long/Longint/pyfory.Int64Type.int64()int64_tint64i64
tagged int648long/Longint/pyfory.TaggedInt64Type.int64({ encoding: "tagged" })int64_tint64i64
uint89short/Shortint/pyfory.UInt8Type.uint8()uint8_tuint8u8
uint1610int/Integerint/pyfory.UInt16Type.uint16()uint16_tuint16u16
fixed uint3211long/Longint/pyfory.FixedUInt32Type.uint32({ encoding: "fixed" })uint32_tuint32u32
uint3212long/Longint/pyfory.UInt32Type.uint32()uint32_tuint32u32
fixed uint6413long/Longint/pyfory.FixedUInt64Type.uint64({ encoding: "fixed" })uint64_tuint64u64
uint6414long/Longint/pyfory.UInt64Type.uint64()uint64_tuint64u64
tagged uint6415long/Longint/pyfory.TaggedUInt64Type.uint64({ encoding: "tagged" })uint64_tuint64u64
float816//////
float1617Float16native float / pyfory.Float16 annotationnumberfory::float16_tfloat16.Float16Float16
bfloat1618BFloat16native float / pyfory.BFloat16 annotationnumberfory::bfloat16_tbfloat16.BFloat16BFloat16
float3219float/Floatfloat/pyfory.Float32Type.float32()floatfloat32f32
float6420double/Doublefloat/pyfory.Float64Type.float64()doublefloat64f64
string21StringstrStringstringstringString/str
list22List/Collectionlist/tuplearrayvectorsliceVec
set23Setset/setfory.SetSet
map24MapdictMapunordered_mapmapHashMap
enum25Enum subclassesenum subclasses/enum/enum
named_enum26Enum subclassesenum subclasses/enum/enum
struct27pojo/recorddata classobjectstruct/classstructstruct
compatible_struct28pojo/recorddata classobjectstruct/classstructstruct
named_struct29pojo/recorddata classobjectstruct/classstructstruct
named_compatible_struct30pojo/recorddata classobjectstruct/classstructstruct
ext31pojo/recorddata classobjectstruct/classstructstruct
named_ext32pojo/recorddata classobjectstruct/classstructstruct
union33Uniontyping.Union/std::variant<Ts...>/tagged union enum
none36nullNonenullstd::monostatenil()
duration37DurationtimedeltaNumberdurationDurationDuration
timestamp38InstantdatetimeNumberstd::chrono::nanosecondsTimeDateTime
date39LocalDatedatetime.dateDatefory::serialization::Datefory.Datechrono::NaiveDate
decimal40BigDecimalDecimalDecimal/fory.Decimalfory::Decimal
binary41byte[]bytes/uint8_t[n]/vector<T>[n]uint8/[]TVec<u8>
array<bool> (bool_array)43bool[]BoolArray / ndarray(np.bool_)BoolArray / Type.boolArray()bool[n][n]bool/[]TVec<bool>
array<int8> (int8_array)44@Int8Type byte[]Int8Array / ndarray(int8)Type.int8Array()int8_t[n]/vector<T>[n]int8/[]TVec<i8>
array<int16> (int16_array)45short[]Int16Array / ndarray(int16)Type.int16Array()int16_t[n]/vector<T>[n]int16/[]TVec<i16>
array<int32> (int32_array)46int[]Int32Array / ndarray(int32)Type.int32Array()int32_t[n]/vector<T>[n]int32/[]TVec<i32>
array<int64> (int64_array)47long[]Int64Array / ndarray(int64)Type.int64Array()int64_t[n]/vector<T>[n]int64/[]TVec<i64>
array<uint8> (uint8_array)48@UInt8Type byte[]UInt8Array / ndarray(uint8)Type.uint8Array()uint8_t[n]/vector<T>[n]uint8/[]TVec<u8>
array<uint16> (uint16_array)49@UInt16Type short[]UInt16Array / ndarray(uint16)Type.uint16Array()uint16_t[n]/vector<T>[n]uint16/[]TVec<u16>
array<uint32> (uint32_array)50@UInt32Type int[]UInt32Array / ndarray(uint32)Type.uint32Array()uint32_t[n]/vector<T>[n]uint32/[]TVec<u32>
array<uint64> (uint64_array)51@UInt64Type long[]UInt64Array / ndarray(uint64)Type.uint64Array()uint64_t[n]/vector<T>[n]uint64/[]TVec<u64>
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]
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]
array<float32> (float32_array)55float[]Float32Array / ndarray(float32)Type.float32Array()float[n]/vector<T>[n]float32/[]TVec<f32>
array<float64> (float64_array)56double[]Float64Array / ndarray(float64)Type.float64Array()double[n]/vector<T>[n]float64/[]TVec<f64>

Notes:

  • Python pyfory.Float16 and pyfory.BFloat16 are reserved annotation markers; scalar values deserialize as native Python float.
  • Python BoolArray, Int8Array, Int16Array, Int32Array, Int64Array, UInt8Array, UInt16Array, UInt32Array, UInt64Array, Float16Array, BFloat16Array, Float32Array, and Float64Array are public dense-array wrappers with list-like sequence behavior.
  • JavaScript BoolArray, fallback Float16Array, and BFloat16Array are public dense-array wrappers backed by Uint8Array or Uint16Array. Scalar float16 and bfloat16 values use number. A JavaScript runtime with native Float16Array may return that native carrier for array<float16>.
  • Java plain byte[] maps to binary. Numeric byte arrays use type-use annotations: @Int8Type byte[] for array<int8> and @UInt8Type byte[] for array<uint8>.
  • Dart uses double plus Float16Type or Bfloat16Type metadata for scalar float16 and bfloat16, BoolList for array<bool>, typed-data lists for integer/float32/float64 arrays, and Float16List / Bfloat16List for array<float16> / array<bfloat16>. Plain Dart List<bool> maps to list<bool> unless a field uses @ArrayField(element: BoolType()) or @ForyField(type: ArrayType(element: BoolType())) with a BoolList carrier.
  • Float16[] and BFloat16[] remain object arrays in xlang mode and serialize with the list wire type.
  • ARRAY (42) is reserved for a future dedicated multi-dimensional array encoding and is not part of the current xlang type-mapping surface.
  • Current xlang uses *_ARRAY for one-dimensional primitive arrays and nested list for multi-dimensional arrays.
  • list<T> and array<T> remain distinct schema kinds. In schema-compatible struct/class field matching only, a direct top-level list<T> field may be read as a direct top-level array<T> field, and a direct top-level array<T> field may be read as a direct top-level list<T> field, when T is one of the dense bool/numeric array domains. Integer list element encodings in the same signedness and width domain match the corresponding dense array element domain. The rule does not apply inside nested collection, map, array, union, or generic positions. A peer list<T> payload that declares nullable or ref-tracked elements must raise a compatible-read error when the local matched field is array<T>.

Type info

Due to differences between type systems of languages, those types can't be mapped one-to-one between languages.

If one host-language type corresponds to multiple Fory scalar encodings, for example Java long can represent fixed, varint, or tagged int64, the user must provide encoding metadata when the default is not the intended schema.

Type annotation

If the type is a field of another class, users can provide meta hints for fields of a type, or for the whole type. Such information can be provided in other languages too:

  • java: use annotation.
  • cpp: use macro and template.
  • golang: use struct tag.
  • python: use typehint.
  • rust: use macro.

Here is en example:

  • Java:

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

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