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.git
The following commit(s) were added to refs/heads/main by this push:
new 34e6c2982 refactor(spec): remove language byte from xlang in protocol
(#3256)
34e6c2982 is described below
commit 34e6c2982c959f664d530b4016e63239142c3cc1
Author: Shawn Yang <[email protected]>
AuthorDate: Wed Feb 4 06:57:23 2026 +0800
refactor(spec): remove language byte from xlang in protocol (#3256)
## Why?
The xlang header no longer needs a per-language byte, and the
ref-tracking naming has drifted across implementations. Align the
protocol header and configuration to be consistent across languages.
## What does this PR do?
- Removes the xlang language byte and updates header write/read paths in
Java, C++, Python, Go, JS, Dart, and Rust to use a single-byte bitmap.
- Simplifies language/config plumbing (Java config uses an `xlang` flag;
language enums/constants removed where unused).
- Renames/refactors ref-tracking fields to `track_ref`/`ref` across
languages and updates fingerprints, serializers, tests, and docs/specs.
## Related issues
#1017
## Does this PR introduce any user-facing change?
Yes — the xlang wire header changes and ref-tracking/config naming
updates are user-visible.
- [x] Does this PR introduce any public API change?
- [x] Does this PR introduce any binary protocol compatibility change?
## Benchmark
---
cpp/fory/serialization/fory.h | 26 ++++------
cpp/fory/serialization/ref_mode.h | 6 +--
cpp/fory/serialization/serialization_test.cc | 22 ++++----
cpp/fory/serialization/serializer.h | 28 ----------
cpp/fory/serialization/skip.cc | 2 +-
cpp/fory/serialization/struct_serializer.h | 2 +-
cpp/fory/serialization/type_resolver.cc | 14 ++---
cpp/fory/serialization/type_resolver.h | 57 +++++++++++---------
dart/packages/fory/lib/fory.dart | 1 -
dart/packages/fory/lib/src/const/lang.dart | 33 ------------
.../lib/src/serializer/fory_header_serializer.dart | 17 ------
docs/guide/java/cross-language.md | 2 +-
docs/guide/rust/cross-language.md | 2 +-
docs/guide/xlang/field-reference-tracking.md | 4 +-
docs/guide/xlang/getting-started.md | 2 +-
docs/guide/xlang/serialization.md | 2 +-
docs/guide/xlang/troubleshooting.md | 2 +-
docs/specification/java_serialization_spec.md | 3 +-
docs/specification/xlang_serialization_spec.md | 23 ++-------
go/fory/fory.go | 12 -----
go/fory/struct.go | 2 +-
.../src/main/java/org/apache/fory/Fory.java | 36 +++----------
.../apache/fory/builder/ObjectCodecOptimizer.java | 6 +--
.../main/java/org/apache/fory/config/Config.java | 12 ++---
.../java/org/apache/fory/config/ForyBuilder.java | 20 ++++----
.../main/java/org/apache/fory/config/Language.java | 6 ---
.../src/test/java/org/apache/fory/ForyTest.java | 2 +-
.../fory/serializer/ArraySerializersTest.java | 2 +-
javascript/packages/fory/lib/fory.ts | 4 +-
javascript/packages/fory/lib/type.ts | 11 ----
python/pyfory/__init__.py | 8 ---
python/pyfory/_fory.py | 47 ++++-------------
python/pyfory/_serializer.py | 2 +-
python/pyfory/collection.pxi | 34 ++++++------
python/pyfory/collection.py | 42 ++++++++-------
python/pyfory/field.py | 2 +-
python/pyfory/meta/typedef.py | 14 ++---
python/pyfory/registry.py | 21 ++++----
python/pyfory/serialization.pyx | 60 ++++++++--------------
python/pyfory/serializer.py | 4 +-
python/pyfory/struct.py | 8 +--
python/pyfory/tests/test_cross_language.py | 2 +-
python/pyfory/tests/test_method.py | 2 +-
python/pyfory/tests/test_serializer.py | 48 +++++++++--------
python/pyfory/tests/test_struct.py | 2 +-
python/pyfory/tests/test_union.py | 4 +-
rust/fory-core/src/fory.rs | 16 ++----
rust/fory-core/src/meta/type_meta.rs | 34 ++++++------
rust/fory-core/src/serializer/skip.rs | 26 +++++-----
rust/fory-core/src/types.rs | 32 ------------
rust/fory-derive/src/object/misc.rs | 20 ++++----
rust/fory-derive/src/object/read.rs | 48 ++++++++---------
rust/fory-derive/src/object/util.rs | 16 +++---
rust/tests/tests/test_meta.rs | 2 +-
54 files changed, 299 insertions(+), 556 deletions(-)
diff --git a/cpp/fory/serialization/fory.h b/cpp/fory/serialization/fory.h
index eb683cb0e..8b1428c96 100644
--- a/cpp/fory/serialization/fory.h
+++ b/cpp/fory/serialization/fory.h
@@ -586,16 +586,14 @@ private:
/// Constructor for ForyBuilder - resolver will be finalized lazily.
explicit Fory(const Config &config, std::shared_ptr<TypeResolver> resolver)
: BaseFory(config, std::move(resolver)), finalized_(false),
- precomputed_header_(compute_header(config.xlang)),
- header_length_(config.xlang ? 2 : 1) {}
+ precomputed_header_(compute_header(config.xlang)) {}
/// Constructor for ThreadSafeFory pool - resolver is already finalized.
struct PreFinalized {};
explicit Fory(const Config &config, std::shared_ptr<TypeResolver> resolver,
PreFinalized)
: BaseFory(config, std::move(resolver)), finalized_(false),
- precomputed_header_(compute_header(config.xlang)),
- header_length_(config.xlang ? 2 : 1) {
+ precomputed_header_(compute_header(config.xlang)) {
// Pre-finalized, immediately create contexts
ensure_finalized();
}
@@ -619,17 +617,12 @@ private:
}
/// Compute the precomputed header value.
- static uint16_t compute_header(bool xlang) {
- uint16_t header = 0;
- // Flags byte at position 0
+ static uint8_t compute_header(bool xlang) {
uint8_t flags = 0;
if (xlang) {
flags |= (1 << 1); // bit 1: xlang flag
}
- header |= flags;
- // Language byte at position 1 (only used if xlang)
- header |= (static_cast<uint16_t>(Language::CPP) << 8);
- return header;
+ return flags;
}
/// Core serialization implementation.
@@ -638,10 +631,10 @@ private:
Result<size_t, Error> serialize_impl(const T &obj, Buffer &buffer) {
size_t start_pos = buffer.writer_index();
- // write precomputed header (2 bytes), then adjust index if not xlang
- buffer.grow(2);
- buffer.unsafe_put<uint16_t>(buffer.writer_index(), precomputed_header_);
- buffer.increase_writer_index(header_length_);
+ // write precomputed header (1 byte flags)
+ buffer.grow(1);
+ buffer.unsafe_put_byte(buffer.writer_index(), precomputed_header_);
+ buffer.increase_writer_index(1);
// Top-level serialization: use Tracking if ref tracking is enabled,
// otherwise NullOnly for nullable handling
@@ -676,8 +669,7 @@ private:
}
bool finalized_;
- uint16_t precomputed_header_;
- uint8_t header_length_;
+ uint8_t precomputed_header_;
std::optional<WriteContext> write_ctx_;
std::optional<ReadContext> read_ctx_;
diff --git a/cpp/fory/serialization/ref_mode.h
b/cpp/fory/serialization/ref_mode.h
index 2482c1771..736a6bf34 100644
--- a/cpp/fory/serialization/ref_mode.h
+++ b/cpp/fory/serialization/ref_mode.h
@@ -48,11 +48,11 @@ enum class RefMode : uint8_t {
Tracking = 2,
};
-/// Create RefMode from nullable and ref_tracking flags.
+/// Create RefMode from nullable and track_ref flags.
/// This is a constexpr function for compile-time field metadata conversion.
FORY_ALWAYS_INLINE constexpr RefMode make_ref_mode(bool nullable,
- bool ref_tracking) {
- if (ref_tracking) {
+ bool track_ref) {
+ if (track_ref) {
return RefMode::Tracking;
}
if (nullable) {
diff --git a/cpp/fory/serialization/serialization_test.cc
b/cpp/fory/serialization/serialization_test.cc
index a089b0b2a..110b75daf 100644
--- a/cpp/fory/serialization/serialization_test.cc
+++ b/cpp/fory/serialization/serialization_test.cc
@@ -236,10 +236,10 @@ TEST(SerializationTest, EnumSerializesOrdinalValue) {
std::vector<uint8_t> bytes = bytes_result.value();
// Xlang spec: enums are serialized as varuint32, not fixed int32_t.
// With registration, we write type_id (ENUM) + user_type_id (1), both as
- // varuint32. Expected: 2 (header) + 1 (ref flag) + 1 (type id) +
- // 1 (user type id) + 1 (ordinal) = 6 bytes
- ASSERT_GE(bytes.size(), 2 + 1 + 1 + 1 + 1);
- size_t offset = 2;
+ // varuint32. Expected: 1 (header) + 1 (ref flag) + 1 (type id) +
+ // 1 (user type id) + 1 (ordinal) = 5 bytes
+ ASSERT_GE(bytes.size(), 1 + 1 + 1 + 1 + 1);
+ size_t offset = 1;
EXPECT_EQ(bytes[offset], static_cast<uint8_t>(NOT_NULL_VALUE_FLAG));
EXPECT_EQ(bytes[offset + 1], static_cast<uint8_t>(TypeId::ENUM));
EXPECT_EQ(bytes[offset + 2], 1);
@@ -257,8 +257,8 @@ TEST(SerializationTest, OldEnumSerializesOrdinalValue) {
std::vector<uint8_t> bytes = bytes_result.value();
// With registration, type_id + user_type_id take 2 bytes
- ASSERT_GE(bytes.size(), 2 + 1 + 1 + 1 + 1);
- size_t offset = 2;
+ ASSERT_GE(bytes.size(), 1 + 1 + 1 + 1 + 1);
+ size_t offset = 1;
EXPECT_EQ(bytes[offset], static_cast<uint8_t>(NOT_NULL_VALUE_FLAG));
EXPECT_EQ(bytes[offset + 1], static_cast<uint8_t>(TypeId::ENUM));
EXPECT_EQ(bytes[offset + 2], 1);
@@ -276,8 +276,8 @@ TEST(SerializationTest,
EnumOrdinalMappingHandlesNonZeroStart) {
std::vector<uint8_t> bytes = bytes_result.value();
// With registration, type_id + user_type_id take 2 bytes
- ASSERT_GE(bytes.size(), 2 + 1 + 1 + 1 + 1);
- size_t offset = 2;
+ ASSERT_GE(bytes.size(), 1 + 1 + 1 + 1 + 1);
+ size_t offset = 1;
EXPECT_EQ(bytes[offset], static_cast<uint8_t>(NOT_NULL_VALUE_FLAG));
EXPECT_EQ(bytes[offset + 1], static_cast<uint8_t>(TypeId::ENUM));
EXPECT_EQ(bytes[offset + 2], 1);
@@ -299,7 +299,7 @@ TEST(SerializationTest,
EnumOrdinalMappingRejectsInvalidOrdinal) {
<< "Serialization failed: " << bytes_result.error().to_string();
std::vector<uint8_t> bytes = bytes_result.value();
- size_t offset = 2;
+ size_t offset = 1;
// With registration, type_id + user_type_id take 2 bytes, ordinal is at
// offset + 3 Replace the valid ordinal with an invalid one (99 as varuint32)
bytes[offset + 3] = 99;
@@ -318,8 +318,8 @@ TEST(SerializationTest,
OldEnumOrdinalMappingHandlesNonZeroStart) {
std::vector<uint8_t> bytes = bytes_result.value();
// With registration, type_id + user_type_id take 2 bytes
- ASSERT_GE(bytes.size(), 2 + 1 + 1 + 1 + 1);
- size_t offset = 2;
+ ASSERT_GE(bytes.size(), 1 + 1 + 1 + 1 + 1);
+ size_t offset = 1;
EXPECT_EQ(bytes[offset], static_cast<uint8_t>(NOT_NULL_VALUE_FLAG));
EXPECT_EQ(bytes[offset + 1], static_cast<uint8_t>(TypeId::ENUM));
EXPECT_EQ(bytes[offset + 2], 1);
diff --git a/cpp/fory/serialization/serializer.h
b/cpp/fory/serialization/serializer.h
index 173576976..5eeae493e 100644
--- a/cpp/fory/serialization/serializer.h
+++ b/cpp/fory/serialization/serializer.h
@@ -60,21 +60,6 @@ namespace serialization {
// Protocol Constants
// ============================================================================
-/// Language identifiers
-/// Must match Java's Language enum ordinal values
-enum class Language : uint8_t {
- XLANG = 0,
- JAVA = 1,
- PYTHON = 2,
- CPP = 3,
- GO = 4,
- JAVASCRIPT = 5,
- RUST = 6,
- DART = 7,
- SCALA = 8,
- KOTLIN = 9,
-};
-
/// Detect if system is little endian
inline bool is_little_endian_system() {
uint32_t test = 1;
@@ -90,7 +75,6 @@ struct HeaderInfo {
bool is_null;
bool is_xlang;
bool is_oob;
- Language language;
uint32_t meta_start_offset; // 0 if not present
};
@@ -117,18 +101,6 @@ inline Result<HeaderInfo, Error> read_header(Buffer
&buffer) {
// Update reader index (1 byte consumed: flags)
buffer.increase_reader_index(1);
- // Language byte after header in xlang mode
- if (info.is_xlang) {
- Error error;
- uint8_t lang_byte = buffer.read_uint8(error);
- if (FORY_PREDICT_FALSE(!error.ok())) {
- return Unexpected(std::move(error));
- }
- info.language = static_cast<Language>(lang_byte);
- } else {
- info.language = Language::JAVA;
- }
-
// Note: Meta start offset would be read here if present
info.meta_start_offset = 0;
diff --git a/cpp/fory/serialization/skip.cc b/cpp/fory/serialization/skip.cc
index 1941b7dd6..9209c4ae8 100644
--- a/cpp/fory/serialization/skip.cc
+++ b/cpp/fory/serialization/skip.cc
@@ -29,7 +29,7 @@ namespace {
// Compute RefMode from field type at runtime.
//
// Per xlang protocol and Java's ObjectSerializer.write_other_field_value:
-// - In xlang mode with ref_tracking=false (default), fields only write
+// - In xlang mode with ref=false (default), fields only write
// ref/null flag if they are nullable
// - Primitives never have ref flags (handled separately)
} // namespace
diff --git a/cpp/fory/serialization/struct_serializer.h
b/cpp/fory/serialization/struct_serializer.h
index 7c7e5ae35..408a288b0 100644
--- a/cpp/fory/serialization/struct_serializer.h
+++ b/cpp/fory/serialization/struct_serializer.h
@@ -2751,7 +2751,7 @@ void read_struct_fields_compatible(T &obj, ReadContext
&ctx,
int16_t field_id = remote_field.field_id;
// Use the precomputed ref_mode from remote field metadata.
- // This is computed from nullable and ref_tracking flags in the remote
+ // This is computed from nullable and track_ref flags in the remote
// field's header during FieldInfo::from_bytes.
RefMode remote_ref_mode = remote_field.field_type.ref_mode;
if (field_id == -1) {
diff --git a/cpp/fory/serialization/type_resolver.cc
b/cpp/fory/serialization/type_resolver.cc
index dbfa69623..a205723d0 100644
--- a/cpp/fory/serialization/type_resolver.cc
+++ b/cpp/fory/serialization/type_resolver.cc
@@ -94,7 +94,7 @@ Result<FieldType, Error> FieldType::read_from(Buffer &buffer,
bool read_flag,
bool null;
bool ref_track;
if (read_flag) {
- // Header layout: type_id:N bits | nullable:1 bit | ref_tracking:1 bit
+ // Header layout: type_id:N bits | nullable:1 bit | track_ref:1 bit
tid = header >> 2;
null = (header & 0b10) != 0;
ref_track = (header & 0b01) != 0;
@@ -131,7 +131,7 @@ Result<std::vector<uint8_t>, Error> FieldInfo::to_bytes()
const {
// write field header:
// header: | field_name_encoding:2bits | size:4bits | nullability:1bit |
- // ref_tracking:1bit |
+ // track_ref:1bit |
const bool use_tag_id = field_id >= 0;
uint8_t encoding_idx = use_tag_id ? 3 : 0; // TAG_ID or UTF8
std::vector<uint8_t> encoded_name;
@@ -165,7 +165,7 @@ Result<std::vector<uint8_t>, Error> FieldInfo::to_bytes()
const {
uint8_t header =
(std::min(FIELD_NAME_SIZE_THRESHOLD, name_size - 1) << 2) & 0x3C;
- if (field_type.ref_tracking) {
+ if (field_type.track_ref) {
header |= 1; // bit 0 for ref tracking
}
if (field_type.nullable) {
@@ -207,7 +207,7 @@ Result<FieldInfo, Error> FieldInfo::from_bytes(Buffer
&buffer) {
// bits 6-7: field name encoding index
uint8_t encoding_idx = static_cast<uint8_t>(header >> 6);
bool use_tag_id = encoding_idx == 3;
- bool ref_tracking = (header & 0b01u) != 0;
+ bool track_ref = (header & 0b01u) != 0;
bool nullable = (header & 0b10u) != 0;
size_t name_size = ((header >> 2) & FIELD_NAME_SIZE_THRESHOLD);
if (name_size == FIELD_NAME_SIZE_THRESHOLD) {
@@ -219,9 +219,9 @@ Result<FieldInfo, Error> FieldInfo::from_bytes(Buffer
&buffer) {
}
name_size += 1;
- // Read field type with nullable and ref_tracking from header
+ // Read field type with nullable and track_ref from header
FORY_TRY(field_type,
- FieldType::read_from(buffer, false, nullable, ref_tracking));
+ FieldType::read_from(buffer, false, nullable, track_ref));
if (use_tag_id) {
FieldInfo info("", std::move(field_type));
@@ -1196,7 +1196,7 @@ std::string TypeMeta::compute_struct_fingerprint(
fingerprint.append(std::to_string(effective_type_id));
fingerprint.push_back(',');
// Use field-level ref tracking flag from FORY_FIELD_TAGS or fory::field<>
- fingerprint.push_back(fi.field_type.ref_tracking ? '1' : '0');
+ fingerprint.push_back(fi.field_type.track_ref ? '1' : '0');
fingerprint.push_back(',');
fingerprint.append(fi.field_type.nullable ? "1;" : "0;");
}
diff --git a/cpp/fory/serialization/type_resolver.h
b/cpp/fory/serialization/type_resolver.h
index 2a8e61d87..cd237c8f7 100644
--- a/cpp/fory/serialization/type_resolver.h
+++ b/cpp/fory/serialization/type_resolver.h
@@ -108,19 +108,19 @@ public:
// Stored as unsigned; 0xffffffff means "unset".
uint32_t user_type_id;
bool nullable;
- bool ref_tracking;
- RefMode ref_mode; // Precomputed from nullable and ref_tracking
+ bool track_ref;
+ RefMode ref_mode; // Precomputed from nullable and track_ref
std::vector<FieldType> generics;
FieldType()
: type_id(0), user_type_id(kInvalidUserTypeId), nullable(false),
- ref_tracking(false), ref_mode(RefMode::None) {}
+ track_ref(false), ref_mode(RefMode::None) {}
FieldType(uint32_t tid, bool null, bool ref_track = false,
std::vector<FieldType> gens = {},
uint32_t user_tid = kInvalidUserTypeId)
: type_id(tid), user_type_id(user_tid), nullable(null),
- ref_tracking(ref_track), ref_mode(make_ref_mode(null, ref_track)),
+ track_ref(ref_track), ref_mode(make_ref_mode(null, ref_track)),
generics(std::move(gens)) {}
/// write field type to buffer
@@ -141,8 +141,8 @@ public:
bool operator==(const FieldType &other) const {
return type_id == other.type_id && nullable == other.nullable &&
- user_type_id == other.user_type_id &&
- ref_tracking == other.ref_tracking && generics == other.generics;
+ user_type_id == other.user_type_id && track_ref == other.track_ref
&&
+ generics == other.generics;
}
bool operator!=(const FieldType &other) const { return !(*this == other); }
@@ -630,20 +630,31 @@ Result<FieldType, Error>
build_field_type_with_resolver(TypeResolver &resolver,
} else {
FieldType ft = FieldTypeBuilder<Decayed>::build(nullable);
if (is_user_type(static_cast<TypeId>(ft.type_id))) {
- FORY_TRY(info, get_type_info_with_resolver<Decayed>(resolver));
- uint32_t resolved_type_id = info->type_id;
- switch (static_cast<TypeId>(resolved_type_id)) {
- case TypeId::NAMED_ENUM:
- resolved_type_id = static_cast<uint32_t>(TypeId::ENUM);
- break;
- case TypeId::TYPED_UNION:
- case TypeId::NAMED_UNION:
- resolved_type_id = static_cast<uint32_t>(TypeId::UNION);
- break;
- default:
- break;
+ if constexpr (std::is_enum_v<Decayed>) {
+ auto info_result = get_type_info_with_resolver<Decayed>(resolver);
+ if (info_result.ok()) {
+ uint32_t resolved_type_id = info_result.value()->type_id;
+ if (resolved_type_id == static_cast<uint32_t>(TypeId::NAMED_ENUM)) {
+ resolved_type_id = static_cast<uint32_t>(TypeId::ENUM);
+ }
+ ft.type_id = resolved_type_id;
+ }
+ } else {
+ FORY_TRY(info, get_type_info_with_resolver<Decayed>(resolver));
+ uint32_t resolved_type_id = info->type_id;
+ switch (static_cast<TypeId>(resolved_type_id)) {
+ case TypeId::NAMED_ENUM:
+ resolved_type_id = static_cast<uint32_t>(TypeId::ENUM);
+ break;
+ case TypeId::TYPED_UNION:
+ case TypeId::NAMED_UNION:
+ resolved_type_id = static_cast<uint32_t>(TypeId::UNION);
+ break;
+ default:
+ break;
+ }
+ ft.type_id = resolved_type_id;
}
- ft.type_id = resolved_type_id;
}
return ft;
}
@@ -838,9 +849,9 @@ template <typename T, size_t Index> struct FieldInfoBuilder
{
}
}
- // Override nullable and ref_tracking from field-level metadata
+ // Override nullable and track_ref from field-level metadata
field_type.nullable = is_nullable;
- field_type.ref_tracking = track_ref;
+ field_type.track_ref = track_ref;
field_type.ref_mode = make_ref_mode(is_nullable, track_ref);
#ifdef FORY_DEBUG
// DEBUG: Print field info for debugging fingerprint mismatch
@@ -911,9 +922,9 @@ template <typename T, size_t Index> struct FieldInfoBuilder
{
}
}
- // Override nullable and ref_tracking from field-level metadata
+ // Override nullable and track_ref from field-level metadata
field_type.nullable = is_nullable;
- field_type.ref_tracking = track_ref;
+ field_type.track_ref = track_ref;
field_type.ref_mode = make_ref_mode(is_nullable, track_ref);
#ifdef FORY_DEBUG
// DEBUG: Print field info for debugging fingerprint mismatch
diff --git a/dart/packages/fory/lib/fory.dart b/dart/packages/fory/lib/fory.dart
index a6493e9ad..61add53da 100644
--- a/dart/packages/fory/lib/fory.dart
+++ b/dart/packages/fory/lib/fory.dart
@@ -38,7 +38,6 @@ export 'src/meta/specs/enum_spec.dart';
export 'src/fory_impl.dart';
// Constants
-export 'src/const/lang.dart';
export 'src/const/obj_type.dart';
// User-related
diff --git a/dart/packages/fory/lib/src/const/lang.dart
b/dart/packages/fory/lib/src/const/lang.dart
deleted file mode 100644
index 024ad1394..000000000
--- a/dart/packages/fory/lib/src/const/lang.dart
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/// Language supported by fory.
-enum Language{
- xlang,
- java,
- python,
- cpp,
- go,
- javascript,
- rust,
- dart;
-
- static int get peerLangBeginIndex => Language.java.index;
- static int get peerLangEndIndex => Language.dart.index;
-}
diff --git a/dart/packages/fory/lib/src/serializer/fory_header_serializer.dart
b/dart/packages/fory/lib/src/serializer/fory_header_serializer.dart
index bc8931090..80bf9e0a3 100644
--- a/dart/packages/fory/lib/src/serializer/fory_header_serializer.dart
+++ b/dart/packages/fory/lib/src/serializer/fory_header_serializer.dart
@@ -19,14 +19,11 @@
import 'package:fory/src/config/fory_config.dart';
import 'package:fory/src/const/fory_header_const.dart';
-import 'package:fory/src/const/lang.dart';
-import 'package:fory/src/exception/deserialization_exception.dart';
import 'package:fory/src/memory/byte_reader.dart';
import 'package:fory/src/memory/byte_writer.dart';
typedef HeaderBrief = ({
bool isXLang,
- Language peerLang,
bool oobEnabled,
});
@@ -47,21 +44,8 @@ final class ForyHeaderSerializer {
assert (isXLang, 'Now Fory Dart only supports xlang mode');
bool oobEnabled = (bitmap & ForyHeaderConst.outOfBandFlag) != 0;
//TODO: oobEnabled unsupported yet.
- // header: peer_lang
- int peerLangInd = br.readInt8();
- if (peerLangInd < Language.peerLangBeginIndex || peerLangInd >
Language.peerLangEndIndex){
- throw DeserializationRangeException(peerLangInd, Language.values);
- }
- Language.values[peerLangInd];
- // if (!conf.xlangMode && serialPack.peerLang != Language.DART){
- // throw ForyException.deserConflict(
- // 'PeerLang:${serialPack.peerLang}',
- // 'XLangMode: false'
- // );
- // }
return (
isXLang: isXLang,
- peerLang: Language.values[peerLangInd],
oobEnabled: oobEnabled,
);
}
@@ -73,7 +57,6 @@ final class ForyHeaderSerializer {
}
// callback must be null
bd.writeInt8(bitmap);
- bd.writeInt8(Language.dart.index);
// Next is xWriteRef, handed over to the outside
}
}
diff --git a/docs/guide/java/cross-language.md
b/docs/guide/java/cross-language.md
index c25115b91..e38160f09 100644
--- a/docs/guide/java/cross-language.md
+++ b/docs/guide/java/cross-language.md
@@ -112,7 +112,7 @@ class Person:
age: pyfory.int32
# Create Fory in xlang mode
-fory = pyfory.Fory(ref_tracking=True)
+fory = pyfory.Fory(ref=True)
# Register with the SAME name as Java
fory.register_type(Person, typename="example.Person")
diff --git a/docs/guide/rust/cross-language.md
b/docs/guide/rust/cross-language.md
index 1aecd7b95..4245a56c8 100644
--- a/docs/guide/rust/cross-language.md
+++ b/docs/guide/rust/cross-language.md
@@ -121,7 +121,7 @@ class Person:
name: str
age: pyfory.int32
-fory = pyfory.Fory(ref_tracking=True)
+fory = pyfory.Fory(ref=True)
fory.register_type(Person, type_id=100) # Same ID as Rust
person = fory.deserialize(bytes_from_rust)
diff --git a/docs/guide/xlang/field-reference-tracking.md
b/docs/guide/xlang/field-reference-tracking.md
index 729f24400..e00d45abd 100644
--- a/docs/guide/xlang/field-reference-tracking.md
+++ b/docs/guide/xlang/field-reference-tracking.md
@@ -43,7 +43,7 @@ Fory fory = Fory.builder()
### Python
```python
-fory = pyfory.Fory(xlang=True, ref_tracking=True)
+fory = pyfory.Fory(xlang=True, ref=True)
```
### Go
@@ -56,7 +56,7 @@ fory := forygo.NewFory(true) // true enables ref tracking
```cpp
auto fory = fory::Fory::create(fory::Config{
- .ref_tracking = true
+ .track_ref = true
});
```
diff --git a/docs/guide/xlang/getting-started.md
b/docs/guide/xlang/getting-started.md
index 4158eeef6..f8bf4a744 100644
--- a/docs/guide/xlang/getting-started.md
+++ b/docs/guide/xlang/getting-started.md
@@ -95,7 +95,7 @@ import pyfory
fory = pyfory.Fory()
# Explicit configuration
-fory = pyfory.Fory(ref_tracking=True)
+fory = pyfory.Fory(ref=True)
```
### Go
diff --git a/docs/guide/xlang/serialization.md
b/docs/guide/xlang/serialization.md
index 8e8439826..791f3c363 100644
--- a/docs/guide/xlang/serialization.md
+++ b/docs/guide/xlang/serialization.md
@@ -458,7 +458,7 @@ class SomeClass:
f2: Dict[str, str]
f3: Dict[str, str]
-fory = pyfory.Fory(ref_tracking=True)
+fory = pyfory.Fory(ref=True)
fory.register_type(SomeClass, typename="example.SomeClass")
obj = SomeClass()
obj.f2 = {"k1": "v1", "k2": "v2"}
diff --git a/docs/guide/xlang/troubleshooting.md
b/docs/guide/xlang/troubleshooting.md
index 26a459512..5c0e59a16 100644
--- a/docs/guide/xlang/troubleshooting.md
+++ b/docs/guide/xlang/troubleshooting.md
@@ -187,7 +187,7 @@ Fory fory = Fory.builder()
```python
# Python
-fory = pyfory.Fory(ref_tracking=True)
+fory = pyfory.Fory(ref=True)
```
### Duplicate Objects
diff --git a/docs/specification/java_serialization_spec.md
b/docs/specification/java_serialization_spec.md
index e3093f2b9..5e72d4226 100644
--- a/docs/specification/java_serialization_spec.md
+++ b/docs/specification/java_serialization_spec.md
@@ -53,8 +53,7 @@ bitmap and uses the same flag bits.
- xlang flag: 1 when serialization uses xlang format, 0 when serialization
uses Java native format.
- oob flag: 1 when `BufferCallback` is not null, 0 otherwise.
-If xlang flag is set, a one byte language ID is written after the bitmap. In
Java native mode (xlang
-flag unset), no language byte is written.
+The header is always a single byte; no language ID is written.
## Reference meta
diff --git a/docs/specification/xlang_serialization_spec.md
b/docs/specification/xlang_serialization_spec.md
index 1256ccb08..670bfe111 100644
--- a/docs/specification/xlang_serialization_spec.md
+++ b/docs/specification/xlang_serialization_spec.md
@@ -257,9 +257,9 @@ The data are serialized using little endian byte order for
all types.
Fory header format for xlang serialization:
```
-| 1 byte bitmap | 1 byte |
-+--------------------------------+------------+
-| flags | language |
+| 1 byte bitmap |
++--------------------------------+
+| flags |
```
Detailed byte layout:
@@ -270,7 +270,6 @@ Byte 0: Bitmap flags
- Bit 1: xlang flag (0x02)
- Bit 2: oob flag (0x04)
- Bits 3-7: reserved
-Byte 1: Language ID (only present when xlang flag is set)
```
- **null flag** (bit 0): 1 when object is null, 0 otherwise. If an object is
null, only this flag is set.
@@ -279,21 +278,6 @@ Byte 1: Language ID (only present when xlang flag is set)
All data is encoded in little-endian format.
-- **language**: 1 byte indicating the source language. This allows
deserializers to optimize for specific language characteristics.
-
-### Language IDs
-
-| Language | ID |
-| ---------- | --- |
-| XLANG | 0 |
-| JAVA | 1 |
-| PYTHON | 2 |
-| CPP | 3 |
-| GO | 4 |
-| JAVASCRIPT | 5 |
-| RUST | 6 |
-| DART | 7 |
-
## Reference Meta
Reference tracking handles whether the object is null, and whether to track
reference for the object by writing
@@ -1532,7 +1516,6 @@ This section provides a step-by-step guide for
implementing Fory xlang serializa
3. **Header Handling**
- [ ] Write/read bitmap flags (null, xlang, oob)
- - [ ] Write/read language ID (when xlang flag is set)
### Phase 2: Basic Type Serializers
diff --git a/go/fory/fory.go b/go/fory/fory.go
index fea76a385..83dd60739 100644
--- a/go/fory/fory.go
+++ b/go/fory/fory.go
@@ -37,15 +37,6 @@ var ErrNoSerializer = errors.New("fory: no serializer
registered for type")
// Constants
// ============================================================================
-// Language constants for protocol header
-const (
- LangXLANG uint8 = iota
- LangJAVA
- LangPYTHON
- LangCPP
- LangGO
-)
-
// Bitmap flags for protocol header
const (
IsNilFlag = 1 << 0
@@ -767,7 +758,6 @@ func writeHeader(ctx *WriteContext, config Config) {
bitmap |= OutOfBandFlag
}
ctx.buffer.WriteByte_(bitmap)
- ctx.buffer.WriteByte_(LangGO)
}
// isNilValue checks if a value is nil, including nil pointers wrapped in any
@@ -809,8 +799,6 @@ func readHeader(ctx *ReadContext) bool {
return true // is null
}
- _ = ctx.buffer.ReadByte(err) // language
-
return false // not null
}
diff --git a/go/fory/struct.go b/go/fory/struct.go
index 18dec4e84..957e4a1d6 100644
--- a/go/fory/struct.go
+++ b/go/fory/struct.go
@@ -1159,7 +1159,7 @@ func (s *structSerializer) computeHash() int32 {
FieldID: field.Meta.TagID,
FieldName: SnakeCase(field.Meta.Name),
TypeID: typeId,
- // Ref is based on explicit tag annotation only, NOT
runtime ref_tracking config
+ // Ref is based on explicit tag annotation only, NOT
runtime track_ref config
// This allows fingerprint to be computed at compile
time for C++/Rust
Ref: field.Meta.TagRefSet && field.Meta.TagRef,
Nullable: nullable,
diff --git a/java/fory-core/src/main/java/org/apache/fory/Fory.java
b/java/fory-core/src/main/java/org/apache/fory/Fory.java
index a744815f3..9285571dd 100644
--- a/java/fory-core/src/main/java/org/apache/fory/Fory.java
+++ b/java/fory-core/src/main/java/org/apache/fory/Fory.java
@@ -35,7 +35,6 @@ import org.apache.fory.collection.IdentityMap;
import org.apache.fory.config.CompatibleMode;
import org.apache.fory.config.Config;
import org.apache.fory.config.ForyBuilder;
-import org.apache.fory.config.Language;
import org.apache.fory.config.LongEncoding;
import org.apache.fory.exception.CopyException;
import org.apache.fory.exception.DeserializationException;
@@ -76,10 +75,9 @@ import org.apache.fory.util.Preconditions;
import org.apache.fory.util.StringUtils;
/**
- * Cross-Lang Data layout: 1byte mask: 1-bit null: 0->null, 1->not null 1-bit
endianness: 0->le,
- * 1->be 1-bit target lang: 0->native, 1->x_lang if x_lang, will write current
process language as a
- * byte into buffer. 1-bit out-of-band serialization enable flag: 0 -> not
enabled, 1 -> enabled.
- * other bits reserved.
+ * Cross-language header layout: 1-byte bitmap.
+ *
+ * <p>Bit 0: null flag, Bit 1: xlang flag, Bit 2: out-of-band flag, Bits 3-7
reserved.
*
* <p>serialize/deserialize is user API for root object serialization,
write/read api is for inner
* serialization.
@@ -119,7 +117,6 @@ public final class Fory implements BaseFory {
private final boolean compressInt;
private final LongEncoding longEncoding;
private final Generics generics;
- private Language peerLanguage;
private BufferCallback bufferCallback;
private Iterator<MemoryBuffer> outOfBandBuffers;
private boolean peerOutOfBandEnabled;
@@ -133,7 +130,7 @@ public final class Fory implements BaseFory {
// Avoid set classLoader in `ForyBuilder`, which won't be clear when
// `org.apache.fory.ThreadSafeFory.clearClassLoader` is called.
config = new Config(builder);
- crossLanguage = config.getLanguage() != Language.JAVA;
+ crossLanguage = config.isXlang();
this.refTracking = config.trackingRef();
this.copyRefTracking = config.copyRef();
this.shareMeta = config.isMetaShareEnabled();
@@ -340,9 +337,9 @@ public final class Fory implements BaseFory {
}
depth = 0;
if (!crossLanguage) {
- write(buffer, obj);
+ writeRef(buffer, obj);
} else {
- xwrite(buffer, obj);
+ xwriteRef(buffer, obj);
}
return buffer;
} catch (Throwable t) {
@@ -410,20 +407,6 @@ public final class Fory implements BaseFory {
}
}
- private void write(MemoryBuffer buffer, Object obj) {
- // reduce caller stack
- if (!refResolver.writeRefOrNull(buffer, obj)) {
- TypeInfo typeInfo = classResolver.getOrUpdateTypeInfo(obj.getClass());
- classResolver.writeTypeInfo(buffer, typeInfo);
- writeData(buffer, typeInfo, obj);
- }
- }
-
- private void xwrite(MemoryBuffer buffer, Object obj) {
- buffer.writeByte((byte) Language.JAVA.ordinal());
- xwriteRef(buffer, obj);
- }
-
/** Serialize a nullable referencable object to <code>buffer</code>. */
public void writeRef(MemoryBuffer buffer, Object obj) {
if (!refResolver.writeRefOrNull(buffer, obj)) {
@@ -886,11 +869,6 @@ public final class Fory implements BaseFory {
return null;
}
boolean isTargetXLang = (bitmap & isCrossLanguageFlag) ==
isCrossLanguageFlag;
- if (isTargetXLang) {
- peerLanguage = Language.values()[buffer.readByte()];
- } else {
- peerLanguage = Language.JAVA;
- }
peerOutOfBandEnabled = (bitmap & isOutOfBandFlag) == isOutOfBandFlag;
if (peerOutOfBandEnabled) {
Preconditions.checkNotNull(
@@ -1382,7 +1360,7 @@ public final class Fory implements BaseFory {
if (depth > 0) {
throwDepthSerializationException();
}
- write(buffer, obj);
+ writeRef(buffer, obj);
} catch (Throwable t) {
throw processSerializationError(t);
} finally {
diff --git
a/java/fory-core/src/main/java/org/apache/fory/builder/ObjectCodecOptimizer.java
b/java/fory-core/src/main/java/org/apache/fory/builder/ObjectCodecOptimizer.java
index 95c5efe7a..cc3bbf230 100644
---
a/java/fory-core/src/main/java/org/apache/fory/builder/ObjectCodecOptimizer.java
+++
b/java/fory-core/src/main/java/org/apache/fory/builder/ObjectCodecOptimizer.java
@@ -41,15 +41,15 @@ import org.apache.fory.util.function.SerializableSupplier;
* <ul>
* <li>compiled code for writing every primitive is 22/21 bytes.
* <li>compiled code for write/read every boxed primitive is 38/35 bytes.
- * <li>compiled code for write/read every boxed primitive with ref_tracking
is 40/81 bytes.
+ * <li>compiled code for write/read every boxed primitive with track_ref is
40/81 bytes.
* <li>compiled code for write/read every final field on average is 41/82
bytes.
* <li>compiled code for write/read every {@literal List<primitive>} on
average is 191/201 bytes.
- * <li>compiled code for write/read every {@literal List<primitive>} with
boxed ref_tracking on
+ * <li>compiled code for write/read every {@literal List<primitive>} with
boxed track_ref on
* average is 194/240 bytes.
* <li>compiled code for write/read every {@literal List<final>} on average
is 196/238 bytes.
* <li>compiled code for write/read every {@literal Map<boxed, boxed>} on
average is 270/196
* bytes.
- * <li>compiled code for write/read every {@literal Map<boxed, boxed>} with
boxed ref_tracking on
+ * <li>compiled code for write/read every {@literal Map<boxed, boxed>} with
boxed track_ref on
* average is 266/296 bytes.
* <li>compiled code for write/read every {@literal Map<final, final>} on
average is 268/292
* bytes.
diff --git a/java/fory-core/src/main/java/org/apache/fory/config/Config.java
b/java/fory-core/src/main/java/org/apache/fory/config/Config.java
index 148deb213..cc2a6c32d 100644
--- a/java/fory-core/src/main/java/org/apache/fory/config/Config.java
+++ b/java/fory-core/src/main/java/org/apache/fory/config/Config.java
@@ -34,7 +34,7 @@ import org.apache.fory.util.Preconditions;
@SuppressWarnings({"rawtypes"})
public class Config implements Serializable {
private final String name;
- private final Language language;
+ private final boolean xlang;
private final boolean trackingRef;
private final boolean stringRefIgnored;
private final boolean timeRefIgnored;
@@ -69,7 +69,7 @@ public class Config implements Serializable {
public Config(ForyBuilder builder) {
name = builder.name;
- language = builder.language;
+ xlang = builder.xlang;
trackingRef = builder.trackingRef;
stringRefIgnored = !trackingRef || builder.stringRefIgnored;
timeRefIgnored = !trackingRef || builder.timeRefIgnored;
@@ -114,8 +114,8 @@ public class Config implements Serializable {
return name;
}
- public Language getLanguage() {
- return language;
+ public boolean isXlang() {
+ return xlang;
}
public boolean trackingRef() {
@@ -324,7 +324,7 @@ public class Config implements Serializable {
&& asyncCompilationEnabled == config.asyncCompilationEnabled
&& deserializeNonexistentClass == config.deserializeNonexistentClass
&& scalaOptimizationEnabled == config.scalaOptimizationEnabled
- && language == config.language
+ && xlang == config.xlang
&& compatibleMode == config.compatibleMode
&& Objects.equals(defaultJDKStreamSerializerType,
config.defaultJDKStreamSerializerType)
&& longEncoding == config.longEncoding;
@@ -334,7 +334,7 @@ public class Config implements Serializable {
public int hashCode() {
return Objects.hash(
name,
- language,
+ xlang,
mapRefLoadFactor,
trackingRef,
stringRefIgnored,
diff --git
a/java/fory-core/src/main/java/org/apache/fory/config/ForyBuilder.java
b/java/fory-core/src/main/java/org/apache/fory/config/ForyBuilder.java
index aed359c6a..b1c76e1a8 100644
--- a/java/fory-core/src/main/java/org/apache/fory/config/ForyBuilder.java
+++ b/java/fory-core/src/main/java/org/apache/fory/config/ForyBuilder.java
@@ -59,7 +59,7 @@ public final class ForyBuilder {
String name;
boolean checkClassVersion = false;
- Language language = Language.JAVA;
+ boolean xlang = false;
boolean trackingRef = false;
boolean copyRef = false;
boolean stringRefIgnored = true;
@@ -93,16 +93,16 @@ public final class ForyBuilder {
public ForyBuilder() {}
/**
- * Whether cross-language serialize the object. If you used fory for java
only, please set
- * language to {@link Language#JAVA}, which will have much better
performance.
+ * Whether cross-language serialize the object. If you used fory for java
only, please keep it in
+ * java mode, which will have much better performance.
*/
public ForyBuilder withLanguage(Language language) {
- this.language = language;
+ this.xlang = language == Language.XLANG;
return this;
}
public ForyBuilder withXlang(boolean xlang) {
- this.language = xlang ? Language.XLANG : Language.JAVA;
+ this.xlang = xlang;
return this;
}
@@ -268,9 +268,7 @@ public final class ForyBuilder {
* class won't evolve.
*/
public ForyBuilder withClassVersionCheck(boolean checkClassVersion) {
- if (language == Language.XLANG
- && compatibleMode == CompatibleMode.SCHEMA_CONSISTENT
- && !checkClassVersion) {
+ if (xlang && compatibleMode == CompatibleMode.SCHEMA_CONSISTENT &&
!checkClassVersion) {
throw new IllegalArgumentException(
"XLANG Schema consistent mode must enable class version check");
}
@@ -430,7 +428,7 @@ public final class ForyBuilder {
classLoader = Fory.class.getClassLoader();
}
}
- if (language != Language.JAVA) {
+ if (xlang) {
stringRefIgnored = true;
longEncoding = LongEncoding.VARINT;
compressInt = true;
@@ -451,7 +449,7 @@ public final class ForyBuilder {
Serializer.class);
}
if (writeNumUtf16BytesForUtf8Encoding == null) {
- writeNumUtf16BytesForUtf8Encoding = language == Language.JAVA;
+ writeNumUtf16BytesForUtf8Encoding = !xlang;
}
if (compatibleMode == CompatibleMode.COMPATIBLE) {
checkClassVersion = false;
@@ -481,7 +479,7 @@ public final class ForyBuilder {
if (metaShareEnabled == null) {
metaShareEnabled = false;
}
- if (language != Language.JAVA) {
+ if (xlang) {
checkClassVersion = true;
}
}
diff --git a/java/fory-core/src/main/java/org/apache/fory/config/Language.java
b/java/fory-core/src/main/java/org/apache/fory/config/Language.java
index 1721cb16b..2e425c35e 100644
--- a/java/fory-core/src/main/java/org/apache/fory/config/Language.java
+++ b/java/fory-core/src/main/java/org/apache/fory/config/Language.java
@@ -23,10 +23,4 @@ package org.apache.fory.config;
public enum Language {
XLANG,
JAVA,
- PYTHON,
- CPP,
- GO,
- JAVASCRIPT,
- RUST,
- DART,
}
diff --git a/java/fory-core/src/test/java/org/apache/fory/ForyTest.java
b/java/fory-core/src/test/java/org/apache/fory/ForyTest.java
index 80c5af116..1211aaa98 100644
--- a/java/fory-core/src/test/java/org/apache/fory/ForyTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/ForyTest.java
@@ -83,7 +83,7 @@ import org.testng.annotations.Test;
public class ForyTest extends ForyTestBase {
@DataProvider(name = "languageConfig")
public static Object[][] languageConfig() {
- return new Object[][] {{Language.JAVA}, {Language.PYTHON}};
+ return new Object[][] {{Language.JAVA}, {Language.XLANG}};
}
@Test(dataProvider = "crossLanguageReferenceTrackingConfig")
diff --git
a/java/fory-core/src/test/java/org/apache/fory/serializer/ArraySerializersTest.java
b/java/fory-core/src/test/java/org/apache/fory/serializer/ArraySerializersTest.java
index bd8e93d66..58afa935e 100644
---
a/java/fory-core/src/test/java/org/apache/fory/serializer/ArraySerializersTest.java
+++
b/java/fory-core/src/test/java/org/apache/fory/serializer/ArraySerializersTest.java
@@ -79,7 +79,7 @@ public class ArraySerializersTest extends ForyTestBase {
for (Class<?> t : types) {
f.getSerializer(t);
}
- if (f.getConfig().getLanguage() == Language.JAVA) {
+ if (!f.getConfig().isXlang()) {
f.getSerializer(Character.class);
f.getSerializer(Character[].class);
f.getSerializer(Character[][].class);
diff --git a/javascript/packages/fory/lib/fory.ts
b/javascript/packages/fory/lib/fory.ts
index f5d9e1c6d..88ab42a6f 100644
--- a/javascript/packages/fory/lib/fory.ts
+++ b/javascript/packages/fory/lib/fory.ts
@@ -21,7 +21,7 @@ import TypeResolver from "./typeResolver";
import { BinaryWriter } from "./writer";
import { BinaryReader } from "./reader";
import { ReferenceResolver } from "./referenceResolver";
-import { ConfigFlags, Serializer, Config, Language, Mode, ForyTypeInfoSymbol,
WithForyClsInfo, TypeId } from "./type";
+import { ConfigFlags, Serializer, Config, Mode, ForyTypeInfoSymbol,
WithForyClsInfo, TypeId } from "./type";
import { OwnershipError } from "./error";
import { InputType, ResultType, StructTypeInfo, TypeInfo } from "./typeInfo";
import { Gen } from "./gen";
@@ -145,7 +145,6 @@ export default class {
if (isOutOfBandEnabled) {
throw new Error("outofband mode is not supported now");
}
- this.binaryReader.uint8(); // skip language
return serializer.readRef();
}
@@ -165,7 +164,6 @@ export default class {
}
bitmap |= ConfigFlags.isCrossLanguageFlag;
this.binaryWriter.uint8(bitmap);
- this.binaryWriter.uint8(Language.JAVASCRIPT);
// reserve fixed size
this.binaryWriter.reserve(serializer.fixedSize);
// start write
diff --git a/javascript/packages/fory/lib/type.ts
b/javascript/packages/fory/lib/type.ts
index 448814b66..18ec15e3e 100644
--- a/javascript/packages/fory/lib/type.ts
+++ b/javascript/packages/fory/lib/type.ts
@@ -239,17 +239,6 @@ export interface Config {
mode: Mode;
}
-export enum Language {
- XLANG = 0,
- JAVA = 1,
- PYTHON = 2,
- CPP = 3,
- GO = 4,
- JAVASCRIPT = 5,
- RUST = 6,
- DART = 7,
-}
-
export interface WithForyClsInfo {
structTypeInfo: StructTypeInfo;
}
diff --git a/python/pyfory/__init__.py b/python/pyfory/__init__.py
index 3b4ad2bbc..38538981a 100644
--- a/python/pyfory/__init__.py
+++ b/python/pyfory/__init__.py
@@ -18,13 +18,9 @@
from pyfory.lib import mmh3
from pyfory._fory import (
Fory,
- Language,
ThreadSafeFory,
)
-PYTHON = Language.PYTHON
-XLANG = Language.XLANG
-
try:
from pyfory.serialization import ENABLE_FORY_CYTHON_SERIALIZATION
except ImportError:
@@ -128,16 +124,12 @@ __version__ = "0.14.1.dev"
__all__ = [
# Core classes
"Fory",
- "Language",
"ThreadSafeFory",
"TypeInfo",
"Buffer",
"DeserializationPolicy",
# Field metadata
"field",
- # Language constants
- "PYTHON",
- "XLANG",
# Type utilities
"record_class_factory",
"get_qualified_classname",
diff --git a/python/pyfory/_fory.py b/python/pyfory/_fory.py
index 8b5832063..9d19353bd 100644
--- a/python/pyfory/_fory.py
+++ b/python/pyfory/_fory.py
@@ -15,7 +15,6 @@
# specific language governing permissions and limitations
# under the License.
-import enum
import logging
import os
from abc import ABC, abstractmethod
@@ -61,17 +60,6 @@ NOT_NULL_STRING_FLAG = NOT_NULL_VALUE_FLAG & 0b11111111 |
(STRING_TYPE_ID << 8)
SMALL_STRING_THRESHOLD = 16
-class Language(enum.Enum):
- XLANG = 0
- JAVA = 1
- PYTHON = 2
- CPP = 3
- GO = 4
- JAVA_SCRIPT = 5
- RUST = 6
- DART = 7
-
-
class BufferObject(ABC):
"""
Fory binary representation of an object.
@@ -147,10 +135,9 @@ class Fory:
"""
__slots__ = (
- "language",
- "is_py",
+ "xlang",
"compatible",
- "ref_tracking",
+ "track_ref",
"ref_resolver",
"type_resolver",
"serialization_context",
@@ -161,7 +148,6 @@ class Fory:
"metastring_resolver",
"_unsupported_callback",
"_unsupported_objects",
- "_peer_language",
"is_peer_out_of_band_enabled",
"max_depth",
"depth",
@@ -179,7 +165,6 @@ class Fory:
policy: DeserializationPolicy = None,
field_nullable: bool = False,
meta_compressor=None,
- **kwargs,
):
"""
Initialize a Fory serialization instance.
@@ -226,23 +211,16 @@ class Fory:
>>> # Cross-language mode with schema evolution
>>> fory = Fory(xlang=True, compatible=True)
"""
- self.language = Language.XLANG if xlang else Language.PYTHON
- if kwargs.get("language") is not None:
- self.language = kwargs.get("language")
- self.is_py = self.language == Language.PYTHON
- if kwargs.get("ref_tracking") is not None:
- ref = kwargs.get("ref_tracking")
- self.ref_tracking = ref
- if self.ref_tracking:
+ self.xlang = xlang
+ self.track_ref = ref
+ if self.track_ref:
self.ref_resolver = MapRefResolver()
else:
self.ref_resolver = NoRefResolver()
- if kwargs.get("require_type_registration") is not None:
- strict = kwargs.get("require_type_registration")
self.strict = _ENABLE_TYPE_REGISTRATION_FORCIBLY or strict
self.policy = policy or DEFAULT_POLICY
self.compatible = compatible
- self.field_nullable = field_nullable if self.is_py else False
+ self.field_nullable = field_nullable if not self.xlang else False
from pyfory.serialization import MetaStringResolver,
SerializationContext
from pyfory.registry import TypeResolver
@@ -256,7 +234,6 @@ class Fory:
self._buffers = None
self._unsupported_callback = None
self._unsupported_objects = None
- self._peer_language = None
self.is_peer_out_of_band_enabled = False
self.max_depth = max_depth
self.depth = 0
@@ -485,11 +462,9 @@ class Fory:
else:
clear_bit(buffer, mask_index, 0)
- if self.language == Language.XLANG:
+ if self.xlang:
# set reader as x_lang.
set_bit(buffer, mask_index, 1)
- # set writer language.
- buffer.write_int8(Language.PYTHON.value)
else:
# set reader as native.
clear_bit(buffer, mask_index, 1)
@@ -499,7 +474,7 @@ class Fory:
clear_bit(buffer, mask_index, 2)
# Type definitions are now written inline (streaming) instead of
deferred to end
- if self.language == Language.PYTHON:
+ if not self.xlang:
self.write_ref(buffer, obj)
else:
self.xwrite_ref(buffer, obj)
@@ -618,10 +593,6 @@ class Fory:
if get_bit(buffer, reader_index, 0):
return None
is_target_x_lang = get_bit(buffer, reader_index, 1)
- if is_target_x_lang:
- self._peer_language = Language(buffer.read_int8())
- else:
- self._peer_language = Language.PYTHON
self.is_peer_out_of_band_enabled = get_bit(buffer, reader_index, 2)
if self.is_peer_out_of_band_enabled:
assert buffers is not None, "buffers shouldn't be null when the
serialized stream is produced with buffer_callback not null."
@@ -682,7 +653,7 @@ class Fory:
serializer = self.type_resolver.read_type_info(buffer).serializer
# Push -1 to read_ref_ids so reference() can pop it and skip reference
tracking
# This handles the case where xread_no_ref is called directly without
xread_ref
- if self.ref_tracking:
+ if self.track_ref:
self.ref_resolver.read_ref_ids.append(-1)
return self._xread_no_ref_internal(buffer, serializer)
diff --git a/python/pyfory/_serializer.py b/python/pyfory/_serializer.py
index ca91b9adc..361f2ec14 100644
--- a/python/pyfory/_serializer.py
+++ b/python/pyfory/_serializer.py
@@ -39,7 +39,7 @@ class Serializer(ABC):
def __init__(self, fory, type_: type):
self.fory = fory
self.type_: type = type_
- self.need_to_write_ref = fory.ref_tracking and not
is_primitive_type(type_)
+ self.need_to_write_ref = fory.track_ref and not
is_primitive_type(type_)
def write(self, buffer, value):
raise NotImplementedError
diff --git a/python/pyfory/collection.pxi b/python/pyfory/collection.pxi
index aa62736c3..df10f1858 100644
--- a/python/pyfory/collection.pxi
+++ b/python/pyfory/collection.pxi
@@ -37,7 +37,6 @@ cdef class CollectionSerializer(Serializer):
cdef TypeResolver type_resolver
cdef MapRefResolver ref_resolver
cdef Serializer elem_serializer
- cdef c_bool is_py
cdef int8_t elem_tracking_ref
cdef elem_type
cdef TypeInfo elem_type_info
@@ -57,7 +56,6 @@ cdef class CollectionSerializer(Serializer):
self.elem_tracking_ref = <int8_t>
(elem_serializer.need_to_write_ref)
if elem_tracking_ref is not None:
self.elem_tracking_ref = <int8_t> (1 if elem_tracking_ref else
0)
- self.is_py = fory.is_py
cdef inline pair[int8_t, int64_t] write_header(self, Buffer buffer, value):
cdef int8_t collect_flag = COLL_DEFAULT_FLAG
@@ -85,7 +83,7 @@ cdef class CollectionSerializer(Serializer):
break
if has_null:
collect_flag |= COLL_HAS_NULL
- if self.fory.ref_tracking:
+ if self.fory.track_ref:
if self.elem_tracking_ref == 1:
collect_flag |= COLL_TRACKING_REF
elif self.elem_tracking_ref == -1:
@@ -109,7 +107,7 @@ cdef class CollectionSerializer(Serializer):
cdef elem_type = elem_type_info.cls
cdef MapRefResolver ref_resolver = self.ref_resolver
cdef TypeResolver type_resolver = self.type_resolver
- cdef c_bool is_py = self.is_py
+ cdef c_bool is_py = not self.fory.xlang
cdef serializer = type(elem_type_info.serializer)
cdef c_bool tracking_ref
cdef c_bool has_null
@@ -237,7 +235,7 @@ cdef class CollectionSerializer(Serializer):
cpdef _write_same_type_no_ref(self, Buffer buffer, value, TypeInfo
typeinfo):
cdef MapRefResolver ref_resolver = self.ref_resolver
cdef TypeResolver type_resolver = self.type_resolver
- if self.is_py:
+ if not self.fory.xlang:
for s in value:
typeinfo.serializer.write(buffer, s)
else:
@@ -248,7 +246,7 @@ cdef class CollectionSerializer(Serializer):
cdef MapRefResolver ref_resolver = self.ref_resolver
cdef TypeResolver type_resolver = self.type_resolver
self.fory.inc_depth()
- if self.is_py:
+ if not self.fory.xlang:
for i in range(len_):
obj = typeinfo.serializer.read(buffer)
self._add_element(collection_, i, obj)
@@ -259,7 +257,7 @@ cdef class CollectionSerializer(Serializer):
self.fory.dec_depth()
cpdef _write_same_type_has_null(self, Buffer buffer, value, TypeInfo
typeinfo):
- if self.is_py:
+ if not self.fory.xlang:
for s in value:
if s is None:
buffer.write_int8(NULL_FLAG)
@@ -277,7 +275,7 @@ cdef class CollectionSerializer(Serializer):
cpdef _read_same_type_has_null(self, Buffer buffer, int64_t len_, object
collection_, TypeInfo typeinfo):
cdef int8_t flag
self.fory.inc_depth()
- if self.is_py:
+ if not self.fory.xlang:
for i in range(len_):
flag = buffer.read_int8()
if flag == NULL_FLAG:
@@ -300,7 +298,7 @@ cdef class CollectionSerializer(Serializer):
cpdef _write_same_type_ref(self, Buffer buffer, value, TypeInfo typeinfo):
cdef MapRefResolver ref_resolver = self.ref_resolver
cdef TypeResolver type_resolver = self.type_resolver
- if self.is_py:
+ if not self.fory.xlang:
for s in value:
if not ref_resolver.write_ref_or_null(buffer, s):
typeinfo.serializer.write(buffer, s)
@@ -312,7 +310,7 @@ cdef class CollectionSerializer(Serializer):
cpdef _read_same_type_ref(self, Buffer buffer, int64_t len_, object
collection_, TypeInfo typeinfo):
cdef MapRefResolver ref_resolver = self.ref_resolver
cdef TypeResolver type_resolver = self.type_resolver
- cdef c_bool is_py = self.is_py
+ cdef c_bool is_py = not self.fory.xlang
self.fory.inc_depth()
for i in range(len_):
ref_id = ref_resolver.try_preserve_ref_id(buffer)
@@ -343,7 +341,7 @@ cdef class ListSerializer(CollectionSerializer):
return list_
cdef int8_t collect_flag = buffer.read_int8()
ref_resolver.reference(list_)
- cdef c_bool is_py = self.is_py
+ cdef c_bool is_py = not self.fory.xlang
cdef TypeInfo typeinfo
cdef uint8_t type_id = 0
cdef c_bool tracking_ref
@@ -465,7 +463,7 @@ cdef class TupleSerializer(CollectionSerializer):
if len_ == 0:
return tuple_
cdef int8_t collect_flag = buffer.read_int8()
- cdef c_bool is_py = self.is_py
+ cdef c_bool is_py = not self.fory.xlang
cdef TypeInfo typeinfo
cdef uint8_t type_id = 0
cdef c_bool tracking_ref
@@ -564,7 +562,7 @@ cdef class SetSerializer(CollectionSerializer):
cdef int32_t ref_id
cdef TypeInfo typeinfo
cdef uint8_t type_id = 0
- cdef c_bool is_py = self.is_py
+ cdef c_bool is_py = not self.fory.xlang
cdef c_bool tracking_ref
cdef c_bool has_null
cdef int8_t head_flag
@@ -708,7 +706,6 @@ cdef class MapSerializer(Serializer):
cdef MapRefResolver ref_resolver
cdef Serializer key_serializer
cdef Serializer value_serializer
- cdef c_bool is_py
cdef int8_t key_tracking_ref
cdef int8_t value_tracking_ref
@@ -726,17 +723,16 @@ cdef class MapSerializer(Serializer):
self.ref_resolver = fory.ref_resolver
self.key_serializer = key_serializer
self.value_serializer = value_serializer
- self.is_py = fory.is_py
self.key_tracking_ref = 0
self.value_tracking_ref = 0
if key_serializer is not None:
self.key_tracking_ref = <int8_t> (key_serializer.need_to_write_ref)
if key_tracking_ref is not None:
- self.key_tracking_ref = <int8_t> (1 if key_tracking_ref and
fory.ref_tracking else 0)
+ self.key_tracking_ref = <int8_t> (1 if key_tracking_ref and
fory.track_ref else 0)
if value_serializer is not None:
self.value_tracking_ref = <int8_t>
(value_serializer.need_to_write_ref)
if value_tracking_ref is not None:
- self.value_tracking_ref = <int8_t> (1 if value_tracking_ref
and fory.ref_tracking else 0)
+ self.value_tracking_ref = <int8_t> (1 if value_tracking_ref
and fory.track_ref else 0)
cpdef inline write(self, Buffer buffer, o):
cdef dict obj = o
@@ -756,7 +752,7 @@ cdef class MapSerializer(Serializer):
cdef int32_t chunk_size_offset, chunk_header, chunk_size
cdef c_bool key_write_ref, value_write_ref
cdef int has_next = PyDict_Next(obj, &pos, <PyObject **>&key_addr,
<PyObject **>&value_addr)
- cdef c_bool is_py = self.is_py
+ cdef c_bool is_py = not self.fory.xlang
while has_next != 0:
key = int2obj(key_addr)
Py_INCREF(key)
@@ -927,7 +923,7 @@ cdef class MapSerializer(Serializer):
cdef c_bool key_is_declared_type, value_is_declared_type
cdef type key_serializer_type, value_serializer_type
cdef int32_t chunk_size
- cdef c_bool is_py = self.is_py
+ cdef c_bool is_py = not self.fory.xlang
self.fory.inc_depth()
while size > 0:
while True:
diff --git a/python/pyfory/collection.py b/python/pyfory/collection.py
index 1fcef05c9..25c58d9b5 100644
--- a/python/pyfory/collection.py
+++ b/python/pyfory/collection.py
@@ -47,7 +47,6 @@ class CollectionSerializer(Serializer):
"type_resolver",
"ref_resolver",
"elem_serializer",
- "is_py",
"elem_tracking_ref",
"elem_type",
"elem_type_info",
@@ -68,7 +67,6 @@ class CollectionSerializer(Serializer):
self.elem_tracking_ref = int(elem_serializer.need_to_write_ref)
if elem_tracking_ref is not None:
self.elem_tracking_ref = 1 if elem_tracking_ref else 0
- self.is_py = fory.is_py
def write_header(self, buffer, value):
collect_flag = COLL_DEFAULT_FLAG
@@ -98,7 +96,7 @@ class CollectionSerializer(Serializer):
if has_null:
collect_flag |= COLL_HAS_NULL
- if self.fory.ref_tracking:
+ if self.fory.track_ref:
if self.elem_tracking_ref == 1:
collect_flag |= COLL_TRACKING_REF
elif self.elem_tracking_ref == -1:
@@ -126,7 +124,7 @@ class CollectionSerializer(Serializer):
self._write_different_types(buffer, value, collect_flag)
def _write_same_type_no_ref(self, buffer, value, typeinfo):
- if self.is_py:
+ if not self.fory.xlang:
for s in value:
typeinfo.serializer.write(buffer, s)
else:
@@ -134,7 +132,7 @@ class CollectionSerializer(Serializer):
typeinfo.serializer.xwrite(buffer, s)
def _write_same_type_has_null(self, buffer, value, typeinfo):
- if self.is_py:
+ if not self.fory.xlang:
for s in value:
if s is None:
buffer.write_int8(NULL_FLAG)
@@ -150,7 +148,7 @@ class CollectionSerializer(Serializer):
typeinfo.serializer.xwrite(buffer, s)
def _write_same_type_ref(self, buffer, value, typeinfo):
- if self.is_py:
+ if not self.fory.xlang:
for s in value:
if not self.ref_resolver.write_ref_or_null(buffer, s):
typeinfo.serializer.write(buffer, s)
@@ -168,7 +166,7 @@ class CollectionSerializer(Serializer):
if not self.ref_resolver.write_ref_or_null(buffer, s):
typeinfo = self.type_resolver.get_type_info(type(s))
self.type_resolver.write_type_info(buffer, typeinfo)
- if self.is_py:
+ if not self.fory.xlang:
typeinfo.serializer.write(buffer, s)
else:
typeinfo.serializer.xwrite(buffer, s)
@@ -177,7 +175,7 @@ class CollectionSerializer(Serializer):
for s in value:
typeinfo = self.type_resolver.get_type_info(type(s))
self.type_resolver.write_type_info(buffer, typeinfo)
- if self.is_py:
+ if not self.fory.xlang:
typeinfo.serializer.write(buffer, s)
else:
typeinfo.serializer.xwrite(buffer, s)
@@ -190,7 +188,7 @@ class CollectionSerializer(Serializer):
buffer.write_int8(NOT_NULL_VALUE_FLAG)
typeinfo = self.type_resolver.get_type_info(type(s))
self.type_resolver.write_type_info(buffer, typeinfo)
- if self.is_py:
+ if not self.fory.xlang:
typeinfo.serializer.write(buffer, s)
else:
typeinfo.serializer.xwrite(buffer, s)
@@ -224,7 +222,7 @@ class CollectionSerializer(Serializer):
def _read_same_type_no_ref(self, buffer, len_, collection_, typeinfo):
self.fory.inc_depth()
- if self.is_py:
+ if not self.fory.xlang:
for _ in range(len_):
self._add_element(collection_,
typeinfo.serializer.read(buffer))
else:
@@ -237,7 +235,7 @@ class CollectionSerializer(Serializer):
def _read_same_type_has_null(self, buffer, len_, collection_, typeinfo):
self.fory.inc_depth()
- if self.is_py:
+ if not self.fory.xlang:
for _ in range(len_):
if buffer.read_int8() == NULL_FLAG:
self._add_element(collection_, None)
@@ -261,7 +259,7 @@ class CollectionSerializer(Serializer):
if ref_id < NOT_NULL_VALUE_FLAG:
obj = self.ref_resolver.get_read_object()
else:
- if self.is_py:
+ if not self.fory.xlang:
obj = typeinfo.serializer.read(buffer)
else:
obj = typeinfo.serializer.xread(buffer)
@@ -276,7 +274,7 @@ class CollectionSerializer(Serializer):
if tracking_ref:
# When ref tracking is enabled, read with ref handling
for i in range(len_):
- elem = get_next_element(buffer, self.ref_resolver,
self.type_resolver, self.is_py)
+ elem = get_next_element(buffer, self.ref_resolver,
self.type_resolver, not self.fory.xlang)
self._add_element(collection_, elem)
elif not has_null:
# When ref tracking is disabled and no nulls, read type info
directly
@@ -284,7 +282,7 @@ class CollectionSerializer(Serializer):
typeinfo = self.type_resolver.read_type_info(buffer)
if typeinfo is None:
elem = None
- elif self.is_py:
+ elif not self.fory.xlang:
elem = typeinfo.serializer.read(buffer)
else:
elem = self.fory.xread_no_ref(buffer,
serializer=typeinfo.serializer)
@@ -299,7 +297,7 @@ class CollectionSerializer(Serializer):
typeinfo = self.type_resolver.read_type_info(buffer)
if typeinfo is None:
elem = None
- elif self.is_py:
+ elif not self.fory.xlang:
elem = typeinfo.serializer.read(buffer)
else:
elem = self.fory.xread_no_ref(buffer,
serializer=typeinfo.serializer)
@@ -409,11 +407,11 @@ class MapSerializer(Serializer):
if key_serializer is not None:
self.key_tracking_ref = bool(key_serializer.need_to_write_ref)
if key_tracking_ref is not None:
- self.key_tracking_ref = bool(key_tracking_ref) and
fory.ref_tracking
+ self.key_tracking_ref = bool(key_tracking_ref) and
fory.track_ref
if value_serializer is not None:
self.value_tracking_ref = bool(value_serializer.need_to_write_ref)
if value_tracking_ref is not None:
- self.value_tracking_ref = bool(value_tracking_ref) and
fory.ref_tracking
+ self.value_tracking_ref = bool(value_tracking_ref) and
fory.track_ref
def write(self, buffer, o):
obj = o
@@ -430,7 +428,7 @@ class MapSerializer(Serializer):
items_iter = iter(obj.items())
key, value = next(items_iter)
has_next = True
- write_ref = fory.write_ref if self.fory.is_py else fory.xwrite_ref
+ write_ref = fory.write_ref if not self.fory.xlang else fory.xwrite_ref
while has_next:
while True:
if key is not None:
@@ -541,7 +539,7 @@ class MapSerializer(Serializer):
if size != 0:
chunk_header = buffer.read_uint8()
key_serializer, value_serializer = self.key_serializer,
self.value_serializer
- read_ref = fory.read_ref if self.fory.is_py else fory.xread_ref
+ read_ref = fory.read_ref if not self.fory.xlang else fory.xread_ref
fory.inc_depth()
while size > 0:
while True:
@@ -626,19 +624,19 @@ class MapSerializer(Serializer):
return map_
def _write_obj(self, serializer, buffer, obj):
- if self.fory.is_py:
+ if not self.fory.xlang:
serializer.write(buffer, obj)
else:
serializer.xwrite(buffer, obj)
def _read_obj(self, serializer, buffer):
- if self.fory.is_py:
+ if not self.fory.xlang:
return serializer.read(buffer)
else:
return serializer.xread(buffer)
def _read_obj_no_ref(self, serializer, buffer):
- if self.fory.is_py:
+ if not self.fory.xlang:
return serializer.read(buffer)
return self.fory.xread_no_ref(buffer, serializer=serializer)
diff --git a/python/pyfory/field.py b/python/pyfory/field.py
index 52ea70fa1..fd67b740c 100644
--- a/python/pyfory/field.py
+++ b/python/pyfory/field.py
@@ -106,7 +106,7 @@ def field(
ref: Whether to enable reference tracking for this field.
- False (default): No tracking, skip IdentityMap overhead
- True: Track references (handles circular refs, shared objects)
- Note: If Fory(ref_tracking=False), all fields use ref=False
+ Note: If Fory(ref=False), all fields use ref=False
regardless of this setting.
ignore: Whether to ignore this field during serialization.
diff --git a/python/pyfory/meta/typedef.py b/python/pyfory/meta/typedef.py
index ee822392e..e7099e864 100644
--- a/python/pyfory/meta/typedef.py
+++ b/python/pyfory/meta/typedef.py
@@ -177,7 +177,7 @@ class TypeDef:
return DataClassSerializer(
fory,
self.cls,
- xlang=not fory.is_py,
+ xlang=fory.xlang,
field_names=field_names,
serializers=self.create_fields_serializer(resolver, field_names),
nullable_fields=nullable_fields,
@@ -465,7 +465,7 @@ def build_field_infos(type_resolver, cls):
nullable_map = {}
visitor = StructTypeIdVisitor(type_resolver.fory, cls)
field_nullable = type_resolver.fory.field_nullable
- global_ref_tracking = type_resolver.fory.ref_tracking
+ global_ref_tracking = type_resolver.fory.track_ref
for field_name in field_names:
field_type_hint = type_hints.get(field_name, typing.Any)
@@ -483,21 +483,21 @@ def build_field_infos(type_resolver, cls):
else:
# For xlang mode: only Optional[T] types are nullable by default
# For native mode: all reference types are nullable by default
- if type_resolver.fory.is_py:
+ if not type_resolver.fory.xlang:
is_nullable = is_optional or not
is_primitive_type(unwrapped_type)
else:
# For xlang: only Optional[T] types are nullable
is_nullable = is_optional
- # Determine ref tracking: field.ref AND global ref_tracking
+ # Determine ref tracking: field.ref AND global track_ref
# For xlang mode: ref tracking defaults to false unless explicitly
annotated
# This matches Java's behavior in TypeResolver.getFieldDescriptors()
if fory_meta is not None:
is_tracking_ref = fory_meta.ref and global_ref_tracking
else:
# In xlang mode, default to false (matches Java's xlang behavior)
- # In native mode, use global ref_tracking setting
- is_tracking_ref = global_ref_tracking if type_resolver.fory.is_py
else False
+ # In native mode, use global track_ref setting
+ is_tracking_ref = global_ref_tracking if not
type_resolver.fory.xlang else False
# Get tag_id from metadata (-1 if not specified)
tag_id = fory_meta.id if fory_meta is not None else -1
@@ -656,7 +656,7 @@ def build_field_type(type_resolver, field_name: str,
type_hint, visitor, is_null
def build_field_type_from_type_ids(type_resolver, field_name: str, type_ids,
visitor, is_nullable=False, type_hint=None):
- tracking_ref = type_resolver.fory.ref_tracking
+ tracking_ref = type_resolver.fory.track_ref
type_id = type_ids[0]
if type_id is None:
type_id = TypeId.UNKNOWN
diff --git a/python/pyfory/registry.py b/python/pyfory/registry.py
index 0f6c70ff9..3d2394002 100644
--- a/python/pyfory/registry.py
+++ b/python/pyfory/registry.py
@@ -28,7 +28,6 @@ from typing import TypeVar, Union
from enum import Enum
from pyfory import ENABLE_FORY_CYTHON_SERIALIZATION
-from pyfory import Language
from pyfory.error import TypeUnregisteredError
from pyfory.serializer import (
@@ -197,7 +196,6 @@ class TypeResolver:
"meta_compressor",
"require_registration",
"metastring_resolver",
- "language",
"_type_id_to_type_info",
"_user_type_id_to_type_info",
"_used_user_type_ids",
@@ -210,7 +208,6 @@ class TypeResolver:
def __init__(self, fory, meta_share=False, meta_compressor=None):
self.fory = fory
self.metastring_resolver = fory.metastring_resolver
- self.language = fory.language
self.require_registration = fory.strict
self._metastr_to_str = dict()
self._metastr_to_type = dict()
@@ -239,7 +236,7 @@ class TypeResolver:
def initialize(self):
self._initialize_common()
- if self.fory.language == Language.PYTHON:
+ if not self.fory.xlang:
self._initialize_py()
else:
self._initialize_xlang()
@@ -452,7 +449,7 @@ class TypeResolver:
raise TypeError(f"type name {typename} and id {type_id} should not
be set at the same time")
if cls in self._types_info:
raise TypeError(f"{cls} registered already")
- register_type = self._register_xtype if self.fory.language ==
Language.XLANG else self._register_pytype
+ register_type = self._register_xtype if self.fory.xlang else
self._register_pytype
return register_type(
cls,
type_id=type_id,
@@ -587,7 +584,7 @@ class TypeResolver:
if user_type_id not in self._user_type_id_to_type_info or not
internal:
self._user_type_id_to_type_info[user_type_id] = typeinfo
self._used_user_type_ids.add(user_type_id)
- elif self.language == Language.PYTHON or not
TypeId.is_namespaced_type(type_id):
+ elif not self.fory.xlang or not TypeId.is_namespaced_type(type_id):
if type_id not in self._type_id_to_type_info or not internal:
self._type_id_to_type_info[type_id] = typeinfo
self._types_info[cls] = typeinfo
@@ -610,7 +607,7 @@ class TypeResolver:
if cls not in self._types_info:
raise TypeUnregisteredError(f"{cls} not registered")
typeinfo = self._types_info[cls]
- if self.fory.language == Language.PYTHON:
+ if not self.fory.xlang:
typeinfo.serializer = serializer
return
prev_type_id = typeinfo.type_id
@@ -653,7 +650,7 @@ class TypeResolver:
logger.info("Type %s not registered", cls)
serializer = self._create_serializer(cls)
type_id = None
- if self.language == Language.PYTHON:
+ if not self.fory.xlang:
if isinstance(serializer, EnumSerializer):
type_id = TypeId.NAMED_ENUM
elif isinstance(serializer, (ObjectSerializer,
StatefulSerializer)):
@@ -683,7 +680,7 @@ class TypeResolver:
# Set a stub serializer FIRST to break recursion for
self-referencing types.
# get_type_info() only calls _set_type_info when serializer is
None,
# so setting stub first prevents re-entry for circular type
references.
- typeinfo.serializer = DataClassStubSerializer(self.fory,
typeinfo.cls, xlang=not self.fory.is_py)
+ typeinfo.serializer = DataClassStubSerializer(self.fory,
typeinfo.cls, xlang=self.fory.xlang)
if self.meta_share:
type_def = encode_typedef(self, typeinfo.cls)
@@ -691,9 +688,9 @@ class TypeResolver:
typeinfo.serializer = type_def.create_serializer(self)
typeinfo.type_def = type_def
else:
- typeinfo.serializer = DataClassSerializer(self.fory,
typeinfo.cls, xlang=not self.fory.is_py)
+ typeinfo.serializer = DataClassSerializer(self.fory,
typeinfo.cls, xlang=self.fory.xlang)
else:
- typeinfo.serializer = DataClassSerializer(self.fory,
typeinfo.cls, xlang=not self.fory.is_py)
+ typeinfo.serializer = DataClassSerializer(self.fory,
typeinfo.cls, xlang=self.fory.xlang)
else:
typeinfo.serializer = self._create_serializer(typeinfo.cls)
@@ -730,7 +727,7 @@ class TypeResolver:
# lazy create serializer to handle nested struct fields.
from pyfory.struct import DataClassStubSerializer
- serializer = DataClassStubSerializer(self.fory, cls, xlang=not
self.fory.is_py)
+ serializer = DataClassStubSerializer(self.fory, cls,
xlang=self.fory.xlang)
elif issubclass(cls, enum.Enum):
serializer = EnumSerializer(self.fory, cls)
elif ("builtin_function_or_method" in str(cls) or
"cython_function_or_method" in str(cls)) and "<locals>" not in str(cls):
diff --git a/python/pyfory/serialization.pyx b/python/pyfory/serialization.pyx
index 006f46523..154c4cc8f 100644
--- a/python/pyfory/serialization.pyx
+++ b/python/pyfory/serialization.pyx
@@ -29,7 +29,6 @@ from typing import TypeVar, Union, Iterable
from pyfory.buffer import get_bit, set_bit, clear_bit
from pyfory import _fory as fmod
-from pyfory._fory import Language
from pyfory._fory import _ENABLE_TYPE_REGISTRATION_FORCIBLY
from pyfory.lib import mmh3
from pyfory.meta.metastring import Encoding
@@ -101,7 +100,7 @@ cdef class MapRefResolver:
efficient serialization of object graphs with duplicate references and
prevents
infinite recursion with circular references.
- When ref_tracking is enabled, duplicate object references are serialized
only once,
+ When track_ref is enabled, duplicate object references are serialized only
once,
with subsequent references storing only the reference ID. During
deserialization,
the resolver maintains a mapping to reconstruct the exact same object
graph structure.
@@ -115,18 +114,18 @@ cdef class MapRefResolver:
cdef vector[PyObject *] read_objects
cdef vector[int32_t] read_ref_ids
cdef object read_object
- cdef c_bool ref_tracking
+ cdef c_bool track_ref
def __cinit__(self, c_bool ref):
self.read_object = None
- self.ref_tracking = ref
+ self.track_ref = ref
# Special methods of extension types must be declared with def, not cdef.
def __dealloc__(self):
self.reset()
cpdef inline c_bool write_ref_or_null(self, Buffer buffer, obj):
- if not self.ref_tracking:
+ if not self.track_ref:
if obj is None:
buffer.write_int8(NULL_FLAG)
return True
@@ -155,7 +154,7 @@ cdef class MapRefResolver:
cpdef inline int8_t read_ref_or_null(self, Buffer buffer):
cdef int8_t head_flag = buffer.read_int8()
- if not self.ref_tracking:
+ if not self.track_ref:
return head_flag
cdef int32_t ref_id
cdef PyObject * obj
@@ -172,7 +171,7 @@ cdef class MapRefResolver:
return head_flag
cpdef inline int32_t preserve_ref_id(self):
- if not self.ref_tracking:
+ if not self.track_ref:
return -1
next_read_ref_id = self.read_objects.size()
self.read_objects.push_back(NULL)
@@ -180,7 +179,7 @@ cdef class MapRefResolver:
return next_read_ref_id
cpdef inline int32_t try_preserve_ref_id(self, Buffer buffer):
- if not self.ref_tracking:
+ if not self.track_ref:
# `NOT_NULL_VALUE_FLAG` can be used as stub reference id because
we use
# `ref_id >= NOT_NULL_VALUE_FLAG` to read data.
return buffer.read_int8()
@@ -213,7 +212,7 @@ cdef class MapRefResolver:
return self.read_ref_ids[length - 1]
cpdef inline reference(self, obj):
- if not self.ref_tracking:
+ if not self.track_ref:
return
cdef int32_t ref_id = self.read_ref_ids.back()
self.read_ref_ids.pop_back()
@@ -228,7 +227,7 @@ cdef class MapRefResolver:
self.read_objects[ref_id] = <PyObject *> obj
cpdef inline get_read_object(self, id_=None):
- if not self.ref_tracking:
+ if not self.track_ref:
return None
if id_ is None:
return self.read_object
@@ -239,7 +238,7 @@ cdef class MapRefResolver:
return <object> obj
cpdef inline set_read_object(self, int32_t ref_id, obj):
- if not self.ref_tracking:
+ if not self.track_ref:
return
if ref_id >= 0:
need_inc = self.read_objects[ref_id] == NULL
@@ -258,7 +257,7 @@ cdef class MapRefResolver:
self.written_objects.clear()
cpdef inline reset_read(self):
- if not self.ref_tracking:
+ if not self.track_ref:
return
for item in self.read_objects:
Py_XDECREF(item)
@@ -627,7 +626,7 @@ cdef class TypeResolver:
else:
if type_id >= self._c_registered_id_to_type_info.size():
self._c_registered_id_to_type_info.resize(type_id * 2, NULL)
- if type_id > 0 and (self.fory.language == Language.PYTHON or not
is_namespaced_type(<TypeId>type_id)):
+ if type_id > 0 and (not self.fory.xlang or not
is_namespaced_type(<TypeId>type_id)):
self._c_registered_id_to_type_info[type_id] = <PyObject *>
typeinfo
self._c_types_info[<uintptr_t> <PyObject *> typeinfo.cls] = <PyObject
*> typeinfo
# Resize if load factor >= 0.4 (using integer arithmetic:
size/capacity >= 4/10)
@@ -1020,10 +1019,9 @@ cdef class Fory:
See Also:
ThreadSafeFory: Thread-safe wrapper for concurrent usage
"""
- cdef readonly object language
- cdef readonly c_bool ref_tracking
+ cdef readonly c_bool xlang
+ cdef readonly c_bool track_ref
cdef readonly c_bool strict
- cdef readonly c_bool is_py
cdef readonly c_bool compatible
cdef readonly c_bool field_nullable
cdef readonly object policy
@@ -1036,7 +1034,6 @@ cdef class Fory:
cdef object _buffers # iterator
cdef object _unsupported_callback
cdef object _unsupported_objects # iterator
- cdef object _peer_language
cdef public bint is_peer_out_of_band_enabled
cdef int32_t max_depth
cdef int32_t depth
@@ -1051,7 +1048,6 @@ cdef class Fory:
max_depth: int = 50,
field_nullable: bool = False,
meta_compressor=None,
- **kwargs,
):
"""
Initialize a Fory serialization instance.
@@ -1098,23 +1094,16 @@ cdef class Fory:
>>> # Cross-language mode with schema evolution
>>> fory = Fory(xlang=True, compatible=True)
"""
- self.language = Language.XLANG if xlang else Language.PYTHON
- if kwargs.get("language") is not None:
- self.language = kwargs.get("language")
- if kwargs.get("ref_tracking") is not None:
- ref = kwargs.get("ref_tracking")
- if kwargs.get("require_type_registration") is not None:
- strict = kwargs.get("require_type_registration")
+ self.xlang = xlang
if _ENABLE_TYPE_REGISTRATION_FORCIBLY or strict:
self.strict = True
else:
self.strict = False
self.policy = policy or DEFAULT_POLICY
self.compatible = compatible
- self.ref_tracking = ref
+ self.track_ref = ref
self.ref_resolver = MapRefResolver(ref)
- self.is_py = self.language == Language.PYTHON
- self.field_nullable = field_nullable if self.is_py else False
+ self.field_nullable = field_nullable if not self.xlang else False
self.metastring_resolver = MetaStringResolver()
self.type_resolver = TypeResolver(self, meta_share=compatible,
meta_compressor=meta_compressor)
self.serialization_context = SerializationContext(fory=self,
scoped_meta_share_enabled=compatible)
@@ -1124,7 +1113,6 @@ cdef class Fory:
self._buffers = None
self._unsupported_callback = None
self._unsupported_objects = None
- self._peer_language = None
self.is_peer_out_of_band_enabled = False
self.depth = 0
self.max_depth = max_depth
@@ -1327,11 +1315,9 @@ cdef class Fory:
else:
clear_bit(buffer, mask_index, 0)
- if self.language == Language.XLANG:
+ if self.xlang:
# set reader as x_lang.
set_bit(buffer, mask_index, 1)
- # set writer language.
- buffer.write_int8(Language.PYTHON.value)
else:
# set reader as native.
clear_bit(buffer, mask_index, 1)
@@ -1340,7 +1326,7 @@ cdef class Fory:
else:
clear_bit(buffer, mask_index, 2)
cdef int32_t start_offset
- if self.language == Language.PYTHON:
+ if not self.xlang:
self.write_ref(buffer, obj)
else:
self.xwrite_ref(buffer, obj)
@@ -1468,10 +1454,6 @@ cdef class Fory:
if get_bit(buffer, reader_index, 0):
return None
cdef c_bool is_target_x_lang = get_bit(buffer, reader_index, 1)
- if is_target_x_lang:
- self._peer_language = Language(buffer.read_int8())
- else:
- self._peer_language = Language.PYTHON
self.is_peer_out_of_band_enabled = get_bit(buffer, reader_index, 2)
if self.is_peer_out_of_band_enabled:
assert buffers is not None, (
@@ -1558,7 +1540,7 @@ cdef class Fory:
serializer = self.type_resolver.read_type_info(buffer).serializer
# Push -1 to read_ref_ids so reference() can pop it and skip reference
tracking
# This handles the case where xread_no_ref is called directly without
xread_ref
- if self.ref_resolver.ref_tracking:
+ if self.ref_resolver.track_ref:
self.ref_resolver.read_ref_ids.push_back(-1)
return self._xread_no_ref_internal(buffer, serializer)
@@ -1841,7 +1823,7 @@ cdef class Serializer:
def __init__(self, fory, type_: Union[type, TypeVar]):
self.fory = fory
self.type_ = type_
- self.need_to_write_ref = fory.ref_tracking and not
is_primitive_type(type_)
+ self.need_to_write_ref = fory.track_ref and not
is_primitive_type(type_)
cpdef write(self, Buffer buffer, value):
raise NotImplementedError(f"write method not implemented in
{type(self)}")
diff --git a/python/pyfory/serializer.py b/python/pyfory/serializer.py
index fb64d3881..00b6a44ab 100644
--- a/python/pyfory/serializer.py
+++ b/python/pyfory/serializer.py
@@ -865,7 +865,7 @@ class TypeSerializer(Serializer):
def _serialize_local_class(self, buffer, cls):
"""Serialize a local class by capturing its creation context."""
- assert self.fory.ref_tracking, "Reference tracking must be enabled for
local classes serialization"
+ assert self.fory.track_ref, "Reference tracking must be enabled for
local classes serialization"
# Basic class information
module = cls.__module__
qualname = cls.__qualname__
@@ -907,7 +907,7 @@ class TypeSerializer(Serializer):
def _deserialize_local_class(self, buffer):
"""Deserialize a local class by recreating it with the captured
context."""
fory = self.fory
- assert fory.ref_tracking, "Reference tracking must be enabled for
local classes deserialization"
+ assert fory.track_ref, "Reference tracking must be enabled for local
classes deserialization"
# Read basic class information
module = buffer.read_string()
qualname = buffer.read_string()
diff --git a/python/pyfory/struct.py b/python/pyfory/struct.py
index 21a622318..ab45111a8 100644
--- a/python/pyfory/struct.py
+++ b/python/pyfory/struct.py
@@ -109,7 +109,7 @@ class FieldInfo:
dynamic: bool # Whether type info is written for this field
# Runtime flags (combines field metadata with global Fory config)
- runtime_ref_tracking: bool # Actual ref tracking: field.ref AND
fory.ref_tracking
+ runtime_ref_tracking: bool # Actual ref tracking: field.ref AND
fory.track_ref
# Derived info
type_id: int # Fory TypeId
@@ -158,7 +158,7 @@ def _default_field_meta(type_hint: type, field_nullable:
bool = False, xlang: bo
nullable = is_optional or not is_primitive_type(unwrapped_type) or
field_nullable
# Default ref=False to preserve original serialization behavior where
non-nullable
# fields use xwrite_no_ref. Users can explicitly set ref=True in
pyfory.field()
- # to enable per-field ref tracking when fory.ref_tracking is enabled.
+ # to enable per-field ref tracking when fory.track_ref is enabled.
# Default dynamic=None for auto-detection based on type and mode
return ForyFieldMeta(id=-1, nullable=nullable, ref=False, ignore=False,
dynamic=None)
@@ -226,7 +226,7 @@ def _extract_field_infos(
# Build FieldInfo list
field_infos: List[FieldInfo] = []
visitor = StructFieldSerializerVisitor(fory)
- global_ref_tracking = fory.ref_tracking
+ global_ref_tracking = fory.track_ref
for index, (field_name, dc_field) in enumerate(active_fields):
meta = field_metas[field_name]
@@ -404,7 +404,7 @@ class DataClassSerializer(Serializer):
if _ENABLE_FORY_PYTHON_JIT:
self.xwrite = self._generated_xwrite_method
self.xread = self._generated_xread_method
- if self.fory.is_py:
+ if not self.fory.xlang:
logger.warning(
"Type of class %s shouldn't be serialized using
cross-language serializer",
clz,
diff --git a/python/pyfory/tests/test_cross_language.py
b/python/pyfory/tests/test_cross_language.py
index b093cad71..14565c581 100644
--- a/python/pyfory/tests/test_cross_language.py
+++ b/python/pyfory/tests/test_cross_language.py
@@ -656,7 +656,7 @@ def test_register_serializer(data_file_path):
fory.serialize(new_obj, buffer=new_buf)
bytes1 = fory.serialize(new_obj)
assert len(bytes1) == len(data_bytes), (bytes1, data_bytes)
- # header can be different to embed writer info like language
+ # header can differ across writers
assert bytes1[8:] == data_bytes[8:]
assert fory.deserialize(fory.serialize(new_obj)) == new_obj, new_obj
print(f"test_register_serializer: {new_obj}")
diff --git a/python/pyfory/tests/test_method.py
b/python/pyfory/tests/test_method.py
index cb3785751..346407ee0 100644
--- a/python/pyfory/tests/test_method.py
+++ b/python/pyfory/tests/test_method.py
@@ -350,7 +350,7 @@ def test_global_methods_without_ref_tracking():
"""Test serialization of global class methods without reference
tracking."""
fory = pyfory.Fory(strict=False, ref=False)
- # Global classes should work even without ref_tracking
+ # Global classes should work even without track_ref
method = GlobalTestClass.class_method
serialized = fory.serialize(method)
deserialized = fory.deserialize(serialized)
diff --git a/python/pyfory/tests/test_serializer.py
b/python/pyfory/tests/test_serializer.py
index e4b4d643a..88fdccce3 100644
--- a/python/pyfory/tests/test_serializer.py
+++ b/python/pyfory/tests/test_serializer.py
@@ -34,7 +34,7 @@ import pytest
import pyfory
from pyfory.buffer import Buffer
-from pyfory import Fory, Language, serialization, EnumSerializer
+from pyfory import Fory, serialization, EnumSerializer
from pyfory.serializer import (
TimestampSerializer,
DateSerializer,
@@ -126,16 +126,16 @@ def test_big_chunk_dict(track_ref):
assert ser_de(fory, dict0) == dict0
[email protected]("language", [Language.XLANG, Language.PYTHON])
-def test_basic_serializer(language):
- fory = Fory(language=language, ref=True)
[email protected]("xlang", [True, False])
+def test_basic_serializer(xlang):
+ fory = Fory(xlang=xlang, ref=True)
typeinfo = fory.type_resolver.get_type_info(datetime.datetime)
assert isinstance(typeinfo.serializer, (TimestampSerializer,
serialization.TimestampSerializer))
- if language == Language.XLANG:
+ if xlang:
assert typeinfo.type_id == TypeId.TIMESTAMP
typeinfo = fory.type_resolver.get_type_info(datetime.date)
assert isinstance(typeinfo.serializer, (DateSerializer,
serialization.DateSerializer))
- if language == Language.XLANG:
+ if xlang:
assert typeinfo.type_id == TypeId.DATE
assert ser_de(fory, True) is True
assert ser_de(fory, False) is False
@@ -164,14 +164,14 @@ def test_basic_serializer(language):
assert ser_de(fory, set_) == set_
[email protected]("language", [Language.XLANG, Language.PYTHON])
-def test_ref_tracking(language):
- fory = Fory(language=language, ref=True)
[email protected]("xlang", [True, False])
+def test_ref_tracking(xlang):
+ fory = Fory(xlang=xlang, ref=True)
# Circular reference test - only works for Python language mode
# XLANG mode doesn't support true circular references during
deserialization
# because the object must be registered after it's fully constructed
- if language == Language.PYTHON:
+ if not xlang:
simple_list = []
simple_list.append(simple_list)
new_simple_list = ser_de(fory, simple_list)
@@ -191,7 +191,7 @@ def test_ref_tracking(language):
"dict2_1": dict2,
}
# Circular reference in dict3 - only works for Python language mode
- if language == Language.PYTHON:
+ if not xlang:
dict3["dict3_0"] = dict3
dict3["dict3_1"] = dict3
new_dict3 = ser_de(fory, dict3)
@@ -201,16 +201,16 @@ def test_ref_tracking(language):
assert new_dict3["dict1_0"] is new_dict3["dict1_1"]
assert new_dict3["dict2_0"] == dict2
assert new_dict3["dict2_0"] is new_dict3["dict2_1"]
- if language == Language.PYTHON:
+ if not xlang:
assert new_dict3["dict3_0"] is new_dict3
assert new_dict3["dict3_0"] is new_dict3["dict3_0"]
[email protected]("language", [Language.PYTHON, Language.XLANG])
-def test_tmp_ref(language):
[email protected]("xlang", [False, True])
+def test_tmp_ref(xlang):
# FIXME this can't simulate the case where new objects are allocated on
memory
# address of released tmp object.
- fory = Fory(language=language, ref=True)
+ fory = Fory(xlang=xlang, ref=True)
buffer = Buffer.allocate(128)
writer_index = buffer.get_writer_index()
x = 1
@@ -230,11 +230,11 @@ def test_tmp_ref(language):
assert l2 is not l3
[email protected]("language", [Language.PYTHON, Language.XLANG])
-def test_multiple_ref(language):
[email protected]("xlang", [False, True])
+def test_multiple_ref(xlang):
# FIXME this can't simulate the case where new objects are allocated on
memory
# address of released tmp object.
- fory = Fory(language=language, ref=True)
+ fory = Fory(xlang=xlang, ref=True)
buffer = Buffer.allocate(128)
for i in range(1000):
fory.serialize([], buffer)
@@ -254,12 +254,10 @@ class RefTestClass2:
self.f1 = f1
[email protected]("language", [Language.PYTHON])
-def test_ref_cleanup(language):
+def test_ref_cleanup():
# FIXME this can't simulate the case where new objects are allocated on
memory
# address of released tmp object.
- fory = Fory(language=language, ref=True, strict=False)
- # TODO support Language.XLANG, current unpickler will error for xlang,
+ fory = Fory(xlang=False, ref=True, strict=False)
o1 = RefTestClass1()
o2 = RefTestClass2(f1=o1)
pickle.loads(pickle.dumps(o2))
@@ -273,9 +271,9 @@ def test_ref_cleanup(language):
fory.deserialize(data)
[email protected]("language", [Language.XLANG, Language.PYTHON])
-def test_array_serializer(language):
- fory = Fory(language=language, ref=True, strict=False)
[email protected]("xlang", [True, False])
+def test_array_serializer(xlang):
+ fory = Fory(xlang=xlang, ref=True, strict=False)
for typecode in PyArraySerializer.typecode_dict.keys():
arr = array.array(typecode, list(range(10)))
new_arr = ser_de(fory, arr)
diff --git a/python/pyfory/tests/test_struct.py
b/python/pyfory/tests/test_struct.py
index 925f39469..265307111 100644
--- a/python/pyfory/tests/test_struct.py
+++ b/python/pyfory/tests/test_struct.py
@@ -209,7 +209,7 @@ def test_data_class_serializer_xlang():
assert type(fory.type_resolver.get_serializer(DataClassObject)) is
pyfory.DataClassSerializer
# Ensure it's using xlang mode indirectly, by checking no JIT methods if
possible,
# or by ensuring it was registered with _register_xtype which now uses
DataClassSerializer(xlang=True)
- # For now, the registration path check is implicit via Language.XLANG
usage.
+ # For now, the registration path check is implicit via xlang=True usage.
# We can also check if the hash is non-zero if it was computed,
# or if the _serializers attribute exists.
serializer_instance = fory.type_resolver.get_serializer(DataClassObject)
diff --git a/python/pyfory/tests/test_union.py
b/python/pyfory/tests/test_union.py
index 1bfd3745a..88607032d 100644
--- a/python/pyfory/tests/test_union.py
+++ b/python/pyfory/tests/test_union.py
@@ -87,7 +87,7 @@ def test_union_with_collections():
def test_union_with_optional():
"""Test Union with Optional (Union[T, None])"""
- fory = Fory(ref_tracking=True)
+ fory = Fory(ref=True)
# Test with non-None value
value: Union[int, None] = 42
@@ -185,7 +185,7 @@ def test_union_with_bytes():
def test_union_cross_language():
"""Test Union with cross-language serialization"""
- fory = Fory(language="xlang")
+ fory = Fory(xlang=True)
# Test with int value
value_int: Union[int, str] = 42
diff --git a/rust/fory-core/src/fory.rs b/rust/fory-core/src/fory.rs
index d4b628964..9d3f82694 100644
--- a/rust/fory-core/src/fory.rs
+++ b/rust/fory-core/src/fory.rs
@@ -24,7 +24,7 @@ use crate::resolver::type_resolver::TypeResolver;
use crate::serializer::ForyDefault;
use crate::serializer::{Serializer, StructSerializer};
use crate::types::config_flags::{IS_CROSS_LANGUAGE_FLAG, IS_NULL_FLAG};
-use crate::types::{Language, RefMode, SIZE_OF_REF_AND_TYPE};
+use crate::types::{RefMode, SIZE_OF_REF_AND_TYPE};
use std::cell::UnsafeCell;
use std::mem;
use std::sync::atomic::{AtomicU64, Ordering};
@@ -150,9 +150,8 @@ impl Fory {
///
/// # Arguments
///
- /// * `xlang` - If `true`, uses the cross-language serialization format
that includes
- /// language metadata and magic numbers for compatibility with Fory
implementations
- /// in other languages (Java, Python, C++, etc.). If `false`, uses a
Rust-only
+ /// * `xlang` - If `true`, uses the cross-language serialization format
compatible with
+ /// other Fory implementations (Java, Python, C++, etc.). If `false`,
uses a Rust-only
/// optimized format.
///
/// # Returns
@@ -862,12 +861,6 @@ impl Fory {
bitmap |= IS_NULL_FLAG;
}
writer.write_u8(bitmap);
- if is_none {
- return;
- }
- if self.config.xlang {
- writer.write_u8(Language::Rust as u8);
- }
}
/// Deserializes data from a byte slice into a value of type `T`.
@@ -1047,9 +1040,6 @@ impl Fory {
if is_none {
return Ok(true);
}
- if peer_is_xlang {
- let _peer_lang = reader.read_u8()?;
- }
Ok(false)
}
}
diff --git a/rust/fory-core/src/meta/type_meta.rs
b/rust/fory-core/src/meta/type_meta.rs
index 22d8f1e84..1cf9d49c4 100644
--- a/rust/fory-core/src/meta/type_meta.rs
+++ b/rust/fory-core/src/meta/type_meta.rs
@@ -99,7 +99,7 @@ pub struct FieldType {
pub type_id: u32,
pub user_type_id: u32,
pub nullable: bool,
- pub ref_tracking: bool,
+ pub track_ref: bool,
pub generics: Vec<FieldType>,
}
@@ -109,7 +109,7 @@ impl FieldType {
type_id,
user_type_id: NO_USER_TYPE_ID,
nullable,
- ref_tracking: false,
+ track_ref: false,
generics,
}
}
@@ -117,14 +117,14 @@ impl FieldType {
pub fn new_with_ref(
type_id: u32,
nullable: bool,
- ref_tracking: bool,
+ track_ref: bool,
generics: Vec<FieldType>,
) -> Self {
FieldType {
type_id,
user_type_id: NO_USER_TYPE_ID,
nullable,
- ref_tracking,
+ track_ref,
generics,
}
}
@@ -141,7 +141,7 @@ impl FieldType {
if nullable {
header |= 2;
}
- if self.ref_tracking {
+ if self.track_ref {
header |= 1;
}
writer.write_var_uint32(header);
@@ -205,7 +205,7 @@ impl FieldType {
type_id,
user_type_id,
nullable: _nullable,
- ref_tracking: _ref_tracking,
+ track_ref: _ref_tracking,
generics: vec![generic],
}
}
@@ -216,7 +216,7 @@ impl FieldType {
type_id,
user_type_id,
nullable: _nullable,
- ref_tracking: _ref_tracking,
+ track_ref: _ref_tracking,
generics: vec![key_generic, val_generic],
}
}
@@ -224,7 +224,7 @@ impl FieldType {
type_id,
user_type_id,
nullable: _nullable,
- ref_tracking: _ref_tracking,
+ track_ref: _ref_tracking,
generics: vec![],
},
})
@@ -269,19 +269,19 @@ impl FieldInfo {
pub fn from_bytes(reader: &mut Reader) -> Result<FieldInfo, Error> {
let header = reader.read_u8()?;
let nullable = (header & 2) != 0;
- let ref_tracking = (header & 1) != 0;
+ let track_ref = (header & 1) != 0;
let encoding_bits = (header >> 6) & 0b11;
// Check if this is field ID mode (encoding bits == 0b11)
if encoding_bits == FIELD_ID_ENCODING_MARKER {
- // Field ID mode: | 0b11:2bits | field_id_low:4bits |
nullable:1bit | ref_tracking:1bit |
+ // Field ID mode: | 0b11:2bits | field_id_low:4bits |
nullable:1bit | track_ref:1bit |
let mut field_id = ((header >> 2) & FIELD_NAME_SIZE_THRESHOLD as
u8) as i16;
if field_id == SMALL_FIELD_ID_THRESHOLD {
field_id += reader.read_varuint32()? as i16;
}
let mut field_type = FieldType::from_bytes(reader, false,
Option::from(nullable))?;
- field_type.ref_tracking = ref_tracking;
+ field_type.track_ref = track_ref;
Ok(FieldInfo {
field_id,
@@ -298,7 +298,7 @@ impl FieldInfo {
name_size += 1;
let mut field_type = FieldType::from_bytes(reader, false,
Option::from(nullable))?;
- field_type.ref_tracking = ref_tracking;
+ field_type.track_ref = track_ref;
let field_name_bytes = reader.read_bytes(name_size)?;
@@ -317,17 +317,17 @@ impl FieldInfo {
let mut buffer = vec![];
let mut writer = Writer::from_buffer(&mut buffer);
let nullable = self.field_type.nullable;
- let ref_tracking = self.field_type.ref_tracking;
+ let track_ref = self.field_type.track_ref;
// Use field ID encoding if:
// 1. field_id >= 0 (user-set or matched from local type), OR
// 2. field_name is empty (ID-encoded field that couldn't be matched -
use ID even if -1)
if self.field_id >= 0 || self.field_name.is_empty() {
- // Field ID mode: | 0b11:2bits | field_id_low:4bits |
nullable:1bit | ref_tracking:1bit |
+ // Field ID mode: | 0b11:2bits | field_id_low:4bits |
nullable:1bit | track_ref:1bit |
// Use max(0, field_id) to handle unmatched fields that have
field_id = -1
let field_id = std::cmp::max(0, self.field_id);
let mut header: u8 = (min(SMALL_FIELD_ID_THRESHOLD, field_id) as
u8) << 2;
- if ref_tracking {
+ if track_ref {
header |= 1;
}
if nullable {
@@ -344,13 +344,13 @@ impl FieldInfo {
} else {
// Field name mode (original behavior)
// field_bytes: | header | type_info | field_name |
- // header: | field_name_encoding:2bits | size:4bits |
nullability:1bit | ref_tracking:1bit |
+ // header: | field_name_encoding:2bits | size:4bits |
nullability:1bit | track_ref:1bit |
let meta_string =
FIELD_NAME_ENCODER.encode_with_encodings(&self.field_name,
FIELD_NAME_ENCODINGS)?;
let name_encoded = meta_string.bytes.as_slice();
let name_size = name_encoded.len() - 1;
let mut header: u8 = (min(FIELD_NAME_SIZE_THRESHOLD, name_size) as
u8) << 2;
- if ref_tracking {
+ if track_ref {
header |= 1;
}
if nullable {
diff --git a/rust/fory-core/src/serializer/skip.rs
b/rust/fory-core/src/serializer/skip.rs
index f50b7b26e..b1b40352d 100644
--- a/rust/fory-core/src/serializer/skip.rs
+++ b/rust/fory-core/src/serializer/skip.rs
@@ -42,7 +42,7 @@ const UNKNOWN_FIELD_TYPE: FieldType = FieldType {
type_id: types::UNKNOWN,
user_type_id: u32::MAX,
nullable: true,
- ref_tracking: false,
+ track_ref: false,
generics: vec![],
};
@@ -84,7 +84,7 @@ pub fn skip_any_value(context: &mut ReadContext,
read_ref_flag: bool) -> Result<
type_id,
user_type_id: u32::MAX,
nullable: true,
- ref_tracking: false,
+ track_ref: false,
generics: vec![UNKNOWN_FIELD_TYPE],
},
None,
@@ -94,7 +94,7 @@ pub fn skip_any_value(context: &mut ReadContext,
read_ref_flag: bool) -> Result<
type_id,
user_type_id: u32::MAX,
nullable: true,
- ref_tracking: false,
+ track_ref: false,
generics: vec![UNKNOWN_FIELD_TYPE, UNKNOWN_FIELD_TYPE],
},
None,
@@ -107,7 +107,7 @@ pub fn skip_any_value(context: &mut ReadContext,
read_ref_flag: bool) -> Result<
type_id,
user_type_id: u32::MAX,
nullable: true,
- ref_tracking: false,
+ track_ref: false,
generics: vec![],
},
Some(type_info),
@@ -121,7 +121,7 @@ pub fn skip_any_value(context: &mut ReadContext,
read_ref_flag: bool) -> Result<
type_id,
user_type_id: u32::MAX,
nullable: true,
- ref_tracking: false,
+ track_ref: false,
generics: vec![],
},
Some(type_info),
@@ -140,7 +140,7 @@ pub fn skip_any_value(context: &mut ReadContext,
read_ref_flag: bool) -> Result<
type_id,
user_type_id: u32::MAX,
nullable: true,
- ref_tracking: false,
+ track_ref: false,
generics: vec![],
},
Some(type_info),
@@ -160,7 +160,7 @@ pub fn skip_any_value(context: &mut ReadContext,
read_ref_flag: bool) -> Result<
type_id,
user_type_id: _user_type_id.unwrap_or(u32::MAX),
nullable: true,
- ref_tracking: false,
+ track_ref: false,
generics: vec![],
},
type_info,
@@ -190,7 +190,7 @@ fn skip_collection(context: &mut ReadContext, field_type:
&FieldType) -> Result<
type_id: type_info_rc.get_type_id() as u32,
user_type_id: type_info_rc.get_user_type_id(),
nullable: has_null,
- ref_tracking: false,
+ track_ref: false,
generics: vec![],
};
type_info = Some(type_info_rc);
@@ -236,7 +236,7 @@ fn skip_map(context: &mut ReadContext, field_type:
&FieldType) -> Result<(), Err
type_id: type_info.get_type_id() as u32,
user_type_id: type_info.get_user_type_id(),
nullable: true,
- ref_tracking: false,
+ track_ref: false,
generics: vec![],
};
value_type_info = Some(type_info);
@@ -261,7 +261,7 @@ fn skip_map(context: &mut ReadContext, field_type:
&FieldType) -> Result<(), Err
type_id: type_info.get_type_id() as u32,
user_type_id: type_info.get_user_type_id(),
nullable: true,
- ref_tracking: false,
+ track_ref: false,
generics: vec![],
};
key_type_info = Some(type_info);
@@ -289,7 +289,7 @@ fn skip_map(context: &mut ReadContext, field_type:
&FieldType) -> Result<(), Err
type_id: type_info.get_type_id() as u32,
user_type_id: type_info.get_user_type_id(),
nullable: true,
- ref_tracking: false,
+ track_ref: false,
generics: vec![],
};
key_type_info = Some(type_info);
@@ -307,7 +307,7 @@ fn skip_map(context: &mut ReadContext, field_type:
&FieldType) -> Result<(), Err
type_id: type_info.get_type_id() as u32,
user_type_id: type_info.get_user_type_id(),
nullable: true,
- ref_tracking: false,
+ track_ref: false,
generics: vec![],
};
value_type_info = Some(type_info);
@@ -776,7 +776,7 @@ pub fn skip_enum_variant(
type_id: types::LIST,
user_type_id: u32::MAX,
nullable: false,
- ref_tracking: false,
+ track_ref: false,
generics: vec![UNKNOWN_FIELD_TYPE],
};
skip_collection(context, &field_type)
diff --git a/rust/fory-core/src/types.rs b/rust/fory-core/src/types.rs
index 825fb0664..eab89a7cf 100644
--- a/rust/fory-core/src/types.rs
+++ b/rust/fory-core/src/types.rs
@@ -15,7 +15,6 @@
// specific language governing permissions and limitations
// under the License.
-use crate::error::Error;
use num_enum::{IntoPrimitive, TryFromPrimitive};
use std::mem;
@@ -497,18 +496,6 @@ pub mod config_flags {
}
#[derive(Debug, PartialEq)]
-pub enum Language {
- Xlang = 0,
- Java = 1,
- Python = 2,
- Cpp = 3,
- Go = 4,
- Javascript = 5,
- Rust = 6,
- Dart = 7,
-}
-
-#[derive(PartialEq)]
pub enum Mode {
// Type declaration must be consistent between serialization peer and
deserialization peer.
SchemaConsistent,
@@ -517,25 +504,6 @@ pub enum Mode {
Compatible,
}
-impl TryFrom<u8> for Language {
- type Error = Error;
-
- fn try_from(num: u8) -> Result<Self, Error> {
- match num {
- 0 => Ok(Language::Xlang),
- 1 => Ok(Language::Java),
- 2 => Ok(Language::Python),
- 3 => Ok(Language::Cpp),
- 4 => Ok(Language::Go),
- 5 => Ok(Language::Javascript),
- 6 => Ok(Language::Rust),
- _ => Err(Error::invalid_data(format!(
- "Unsupported language code, value:{num}"
- ))),
- }
- }
-}
-
// every object start with i8 i16 reference flag and type flag
pub const SIZE_OF_REF_AND_TYPE: usize = mem::size_of::<i8>() +
mem::size_of::<i16>();
diff --git a/rust/fory-derive/src/object/misc.rs
b/rust/fory-derive/src/object/misc.rs
index 0aae55a09..0e1cd8831 100644
--- a/rust/fory-derive/src/object/misc.rs
+++ b/rust/fory-derive/src/object/misc.rs
@@ -85,11 +85,11 @@ pub fn gen_field_fields_info(source_fields:
&[SourceField<'_>]) -> TokenStream {
let meta = parse_field_meta(field).unwrap_or_default();
let type_class = classify_field_type(ty);
// For nullable, check both the classified type AND whether outer type
is Option
- // This handles Option<Rc<T>> correctly - classify_field_type returns
Rc for ref_tracking,
+ // This handles Option<Rc<T>> correctly - classify_field_type returns
Rc for track_ref,
// but we also need to detect that the outer wrapper is Option for
nullable.
let is_outer_option = is_option_type(ty);
let nullable = meta.effective_nullable(type_class) || is_outer_option;
- let ref_tracking = meta.effective_ref(type_class);
+ let track_ref = meta.effective_ref(type_class);
// Only use explicit field ID when user sets #[fory(id = N)]
// Otherwise use -1 to indicate field name encoding should be used
let field_id = if meta.uses_tag_id() {
@@ -160,7 +160,7 @@ pub fn gen_field_fields_info(source_fields:
&[SourceField<'_>]) -> TokenStream {
type_id: #type_id_ts,
user_type_id: u32::MAX,
nullable: #nullable,
- ref_tracking: #ref_tracking,
+ track_ref: #track_ref,
generics: Vec::new()
}
)
@@ -183,7 +183,7 @@ pub fn gen_field_fields_info(source_fields:
&[SourceField<'_>]) -> TokenStream {
type_id: #type_id_ts,
user_type_id: u32::MAX,
nullable: #nullable,
- ref_tracking: #ref_tracking,
+ track_ref: #track_ref,
generics: Vec::new()
}
)
@@ -198,7 +198,7 @@ pub fn gen_field_fields_info(source_fields:
&[SourceField<'_>]) -> TokenStream {
{
let mut ft = #generic_token;
ft.nullable = #nullable;
- ft.ref_tracking = #ref_tracking;
+ ft.track_ref = #track_ref;
ft
}
)
@@ -211,12 +211,12 @@ pub fn gen_field_fields_info(source_fields:
&[SourceField<'_>]) -> TokenStream {
type_id: fory_core::types::TypeId::LIST as u32,
user_type_id: u32::MAX,
nullable: #nullable,
- ref_tracking: #ref_tracking,
+ track_ref: #track_ref,
generics: vec![fory_core::meta::FieldType {
type_id: fory_core::types::TypeId::UNKNOWN as u32,
user_type_id: u32::MAX,
nullable: false,
- ref_tracking: false,
+ track_ref: false,
generics: Vec::new()
}]
})
@@ -232,14 +232,14 @@ pub fn gen_field_fields_info(source_fields:
&[SourceField<'_>]) -> TokenStream {
type_id: fory_core::types::TypeId::MAP as u32,
user_type_id: u32::MAX,
nullable: #nullable,
- ref_tracking: #ref_tracking,
+ track_ref: #track_ref,
generics: vec![
#key_generic_token,
fory_core::meta::FieldType {
type_id: fory_core::types::TypeId::UNKNOWN as
u32,
user_type_id: u32::MAX,
nullable: false,
- ref_tracking: false,
+ track_ref: false,
generics: Vec::new()
}
]
@@ -252,7 +252,7 @@ pub fn gen_field_fields_info(source_fields:
&[SourceField<'_>]) -> TokenStream {
type_id: fory_core::types::TypeId::UNKNOWN as u32,
user_type_id: u32::MAX,
nullable: #nullable,
- ref_tracking: #ref_tracking,
+ track_ref: #track_ref,
generics: Vec::new()
})
}
diff --git a/rust/fory-derive/src/object/read.rs
b/rust/fory-derive/src/object/read.rs
index 2635f3b71..ba1e7aa44 100644
--- a/rust/fory-derive/src/object/read.rs
+++ b/rust/fory-derive/src/object/read.rs
@@ -591,20 +591,20 @@ pub(crate) fn gen_read_compatible_match_arm_body(
}
StructField::VecBox(_) => {
// Vec<Box<dyn Any>> uses standard Vec deserialization with
polymorphic elements
- // Check nullable and ref_tracking flags from remote field info
+ // Check nullable and track_ref flags from remote field info
quote! {
let read_ref_flag =
fory_core::serializer::util::field_need_write_ref_into(
_field.field_type.type_id,
_field.field_type.nullable,
);
- let ref_mode = if _field.field_type.ref_tracking {
+ let ref_mode = if _field.field_type.track_ref {
fory_core::RefMode::Tracking
} else if read_ref_flag {
fory_core::RefMode::NullOnly
} else {
fory_core::RefMode::None
};
- if read_ref_flag || _field.field_type.ref_tracking {
+ if read_ref_flag || _field.field_type.track_ref {
#var_name = Some(<#ty as
fory_core::Serializer>::fory_read(context, ref_mode, false)?);
} else {
#var_name = Some(<#ty as
fory_core::Serializer>::fory_read_data(context)?);
@@ -613,20 +613,20 @@ pub(crate) fn gen_read_compatible_match_arm_body(
}
StructField::HashMapBox(_, _) => {
// HashMap<K, Box<dyn Any>> uses standard HashMap
deserialization with polymorphic values
- // Check nullable and ref_tracking flags from remote field info
+ // Check nullable and track_ref flags from remote field info
quote! {
let read_ref_flag =
fory_core::serializer::util::field_need_write_ref_into(
_field.field_type.type_id,
_field.field_type.nullable,
);
- let ref_mode = if _field.field_type.ref_tracking {
+ let ref_mode = if _field.field_type.track_ref {
fory_core::RefMode::Tracking
} else if read_ref_flag {
fory_core::RefMode::NullOnly
} else {
fory_core::RefMode::None
};
- if read_ref_flag || _field.field_type.ref_tracking {
+ if read_ref_flag || _field.field_type.track_ref {
#var_name = Some(<#ty as
fory_core::Serializer>::fory_read(context, ref_mode, false)?);
} else {
#var_name = Some(<#ty as
fory_core::Serializer>::fory_read_data(context)?);
@@ -665,14 +665,14 @@ pub(crate) fn gen_read_compatible_match_arm_body(
}
StructField::Forward => {
// Forward types (trait objects, forward references) -
polymorphic, always need type info
- // Use remote field's ref_tracking flag for ref_mode
+ // Use remote field's track_ref flag for ref_mode
quote! {
let read_ref_flag =
fory_core::serializer::util::field_need_write_ref_into(
_field.field_type.type_id,
_field.field_type.nullable,
);
- // Use RefMode::Tracking if remote field has ref_tracking
enabled
- let ref_mode = if _field.field_type.ref_tracking {
+ // Use RefMode::Tracking if remote field has track_ref
enabled
+ let ref_mode = if _field.field_type.track_ref {
fory_core::RefMode::Tracking
} else if read_ref_flag {
fory_core::RefMode::NullOnly
@@ -711,15 +711,15 @@ pub(crate) fn gen_read_compatible_match_arm_body(
_field.field_type.type_id,
_field.field_type.nullable,
);
- // Use RefMode::Tracking if remote field has
ref_tracking enabled
- let ref_mode = if _field.field_type.ref_tracking {
+ // Use RefMode::Tracking if remote field has
track_ref enabled
+ let ref_mode = if _field.field_type.track_ref {
fory_core::RefMode::Tracking
} else if read_ref_flag {
fory_core::RefMode::NullOnly
} else {
fory_core::RefMode::None
};
- if read_ref_flag || _field.field_type.ref_tracking
{
+ if read_ref_flag || _field.field_type.track_ref {
#var_name = Some(<#ty as
fory_core::Serializer>::fory_read(context, ref_mode, false)?);
} else {
#var_name = Some(<#ty as
fory_core::Serializer>::fory_read_data(context)?);
@@ -732,8 +732,8 @@ pub(crate) fn gen_read_compatible_match_arm_body(
_field.field_type.type_id,
_field.field_type.nullable,
);
- // Use RefMode::Tracking if remote field has
ref_tracking enabled
- let ref_mode = if _field.field_type.ref_tracking {
+ // Use RefMode::Tracking if remote field has
track_ref enabled
+ let ref_mode = if _field.field_type.track_ref {
fory_core::RefMode::Tracking
} else if read_ref_flag {
fory_core::RefMode::NullOnly
@@ -754,15 +754,15 @@ pub(crate) fn gen_read_compatible_match_arm_body(
_field.field_type.type_id,
_field.field_type.nullable,
);
- // Use RefMode::Tracking if remote field has
ref_tracking enabled
- let ref_mode = if _field.field_type.ref_tracking {
+ // Use RefMode::Tracking if remote field has
track_ref enabled
+ let ref_mode = if _field.field_type.track_ref {
fory_core::RefMode::Tracking
} else if read_ref_flag {
fory_core::RefMode::NullOnly
} else {
fory_core::RefMode::None
};
- if read_ref_flag || _field.field_type.ref_tracking
{
+ if read_ref_flag || _field.field_type.track_ref {
#var_name = Some(<#ty as
fory_core::Serializer>::fory_read(context, ref_mode, false)?);
} else {
#var_name = Some(<#ty as
fory_core::Serializer>::fory_read_data(context)?);
@@ -774,15 +774,15 @@ pub(crate) fn gen_read_compatible_match_arm_body(
_field.field_type.type_id,
_field.field_type.nullable,
);
- // Use RefMode::Tracking if remote field has
ref_tracking enabled
- let ref_mode = if _field.field_type.ref_tracking {
+ // Use RefMode::Tracking if remote field has
track_ref enabled
+ let ref_mode = if _field.field_type.track_ref {
fory_core::RefMode::Tracking
} else if read_ref_flag {
fory_core::RefMode::NullOnly
} else {
fory_core::RefMode::None
};
- if read_ref_flag || _field.field_type.ref_tracking
{
+ if read_ref_flag || _field.field_type.track_ref {
#var_name = <#ty as
fory_core::Serializer>::fory_read(context, ref_mode, false)?;
} else {
#var_name = <#ty as
fory_core::Serializer>::fory_read_data(context)?;
@@ -795,8 +795,8 @@ pub(crate) fn gen_read_compatible_match_arm_body(
_field.field_type.type_id,
_field.field_type.nullable,
);
- // Use RefMode::Tracking if remote field has
ref_tracking enabled
- let ref_mode = if _field.field_type.ref_tracking {
+ // Use RefMode::Tracking if remote field has track_ref
enabled
+ let ref_mode = if _field.field_type.track_ref {
fory_core::RefMode::Tracking
} else if read_ref_flag {
fory_core::RefMode::NullOnly
@@ -815,8 +815,8 @@ pub(crate) fn gen_read_compatible_match_arm_body(
_field.field_type.type_id,
_field.field_type.nullable,
);
- // Use RefMode::Tracking if remote field has
ref_tracking enabled
- let ref_mode = if _field.field_type.ref_tracking {
+ // Use RefMode::Tracking if remote field has track_ref
enabled
+ let ref_mode = if _field.field_type.track_ref {
fory_core::RefMode::Tracking
} else if read_ref_flag {
fory_core::RefMode::NullOnly
diff --git a/rust/fory-derive/src/object/util.rs
b/rust/fory-derive/src/object/util.rs
index 5080a4bc9..84c8f9fb0 100644
--- a/rust/fory-derive/src/object/util.rs
+++ b/rust/fory-derive/src/object/util.rs
@@ -593,7 +593,7 @@ pub(super) fn generic_tree_to_tokens(node: &TypeNode) ->
TokenStream {
};
// If Rc or Arc, unwrap to inner type - these are reference wrappers
- // that don't add type info to the field type (handled by ref_tracking
flag)
+ // that don't add type info to the field type (handled by track_ref flag)
let base_node = if base_node.name == "Rc" || base_node.name == "Arc" {
if let Some(inner) = base_node.generics.first() {
inner
@@ -674,7 +674,7 @@ pub(super) fn generic_tree_to_tokens(node: &TypeNode) ->
TokenStream {
type_id,
user_type_id,
nullable: #nullable,
- ref_tracking: false,
+ track_ref: false,
generics,
}
}
@@ -1321,7 +1321,7 @@ struct FieldFingerprintInfo {
/// Whether the field has explicit nullable=true/false set via
#[fory(nullable)]
explicit_nullable: Option<bool>,
/// Whether reference tracking is enabled
- ref_tracking: bool,
+ track_ref: bool,
/// The type ID (UNKNOWN for user-defined types including enums/unions)
type_id: u32,
/// Whether the field type is `Option<T>`
@@ -1409,7 +1409,7 @@ fn compute_struct_fingerprint(fields: &[&Field]) ->
String {
};
let type_class = classify_field_type(&field.ty);
- let ref_tracking = meta.effective_ref(type_class);
+ let track_ref = meta.effective_ref(type_class);
let explicit_nullable = meta.nullable;
// Get compile-time TypeId, considering encoding attributes for
u32/u64 fields
@@ -1429,7 +1429,7 @@ fn compute_struct_fingerprint(fields: &[&Field]) ->
String {
field_infos.push(FieldFingerprintInfo {
name_or_id,
explicit_nullable,
- ref_tracking,
+ track_ref,
type_id,
is_option_type,
});
@@ -1441,7 +1441,7 @@ fn compute_struct_fingerprint(fields: &[&Field]) ->
String {
// Build fingerprint string
let mut fingerprint = String::new();
for info in &field_infos {
- let ref_flag = if info.ref_tracking { "1" } else { "0" };
+ let ref_flag = if info.track_ref { "1" } else { "0" };
let nullable = match info.explicit_nullable {
Some(true) => true,
Some(false) => false,
@@ -1522,9 +1522,9 @@ pub(crate) fn determine_field_ref_mode(field:
&syn::Field) -> FieldRefMode {
let meta = parse_field_meta(field).unwrap_or_default();
let type_class = classify_field_type(&field.ty);
let nullable = meta.effective_nullable(type_class);
- let ref_tracking = meta.effective_ref(type_class);
+ let track_ref = meta.effective_ref(type_class);
- if ref_tracking {
+ if track_ref {
FieldRefMode::Tracking
} else if nullable {
FieldRefMode::NullOnly
diff --git a/rust/tests/tests/test_meta.rs b/rust/tests/tests/test_meta.rs
index 4d32296b8..deae54dd7 100644
--- a/rust/tests/tests/test_meta.rs
+++ b/rust/tests/tests/test_meta.rs
@@ -33,7 +33,7 @@ fn test_meta_hash() {
type_id: TypeId::BOOL as u32,
user_type_id: u32::MAX,
nullable: true,
- ref_tracking: false,
+ track_ref: false,
generics: vec![],
},
}],
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]