-
Notifications
You must be signed in to change notification settings - Fork 358
Closed
Labels
Description
Feature Request
Add a RefMode enum to Rust similar to Go's implementation, and change all write_ref_info/read_ref_info boolean parameters in Serializer to accept RefMode, enabling fine-grained control of reference tracking per type and per field.
Is your feature request related to a problem? Please describe
Currently Rust uses a boolean write_ref_info/read_ref_info parameter which only distinguishes between "write ref flag" vs "don't write ref flag". This doesn't support:
- Nullable types without ref tracking (like
Option<T>where T is not a shared ref) - Explicit control over shared reference tracking per field via
#[fory(ref=false)]attribute - Alignment with Go's
RefModedesign which has three modes:None,NullOnly,Tracking
Describe the solution you'd like
RefMode Enum Design
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[repr(u8)]
pub enum RefMode {
#[default]
None = 0, // No ref flag written/read (primitives, non-nullable types)
NullOnly = 1, // Write NULL(-3) or NOT_NULL(-1), no ref tracking
Tracking = 2, // Full ref tracking with REF(-2) and REF_VALUE(0) flags
}RefMode Semantics
| RefMode | Write Behavior | Read Behavior |
|---|---|---|
None |
No ref flag written | No ref flag read |
NullOnly |
Write -3 (null) or -1 (not null) |
Read flag, return default on null |
Tracking |
Full ref tracking with all 4 flags | Full ref resolution |
Key Changes
- Serializer trait signature change:
fn fory_write(&self, context: &mut WriteContext, ref_mode: RefMode, write_type_info: bool, has_generics: bool) -> Result<(), Error>
fn fory_read(context: &mut ReadContext, ref_mode: RefMode, read_type_info: bool) -> Result<Self, Error>-
Per-field RefMode determination based on:
- Type classification (primitive →
None, Option →NullOnly, Rc/Arc →Tracking) - Field meta attributes:
#[fory(ref=false)]to disable tracking,#[fory(nullable)]for null support
- Type classification (primitive →
-
Performance optimization for non-trackable types:
- Use single
if ref_mode != RefMode::Noneinstead of match for primitives/strings #[inline(always)]on hot paths
- Use single
Describe alternatives you've considered
- Two boolean parameters (
nullable: bool,tracking: bool): More verbose, 4 combinations when only 3 are needed - Keep current boolean: Loses the ability to distinguish nullable-without-tracking from non-nullable
Additional context
Go Reference Implementation
type RefMode uint8
const (
RefModeNone RefMode = iota // skip ref handling entirely
RefModeNullOnly // only null check, no ref tracking
RefModeTracking // full circular ref support
)Protocol Specification (from xlang_serialization_spec.md)
Reference flags:
NULL FLAG(-3): Object is nullREF FLAG(-2): Object was already serialized (+ varint ref ID)NOT_NULL VALUE FLAG(-1): Non-null, no ref trackingREF VALUE FLAG(0): Referencable, first occurrence
Files to Modify
rust/fory-core/src/types.rs- Add RefMode enumrust/fory-core/src/serializer/core.rs- Update Serializer traitrust/fory-core/src/serializer/*.rs- Update all serializer implementationsrust/fory-derive/src/object/write.rs- Update generated coderust/fory-derive/src/object/read.rs- Update generated coderust/fory-derive/src/object/util.rs- Adddetermine_field_ref_mode()helper