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
RefMode design 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
-
Performance optimization for non-trackable types:
- Use single
if ref_mode != RefMode::None instead of match for primitives/strings
#[inline(always)] on hot paths
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 null
REF FLAG (-2): Object was already serialized (+ varint ref ID)
NOT_NULL VALUE FLAG (-1): Non-null, no ref tracking
REF VALUE FLAG (0): Referencable, first occurrence
Files to Modify
rust/fory-core/src/types.rs - Add RefMode enum
rust/fory-core/src/serializer/core.rs - Update Serializer trait
rust/fory-core/src/serializer/*.rs - Update all serializer implementations
rust/fory-derive/src/object/write.rs - Update generated code
rust/fory-derive/src/object/read.rs - Update generated code
rust/fory-derive/src/object/util.rs - Add determine_field_ref_mode() helper
Feature Request
Add a
RefModeenum to Rust similar to Go's implementation, and change allwrite_ref_info/read_ref_infoboolean parameters inSerializerto acceptRefMode, 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_infoparameter which only distinguishes between "write ref flag" vs "don't write ref flag". This doesn't support:Option<T>where T is not a shared ref)#[fory(ref=false)]attributeRefModedesign which has three modes:None,NullOnly,TrackingDescribe the solution you'd like
RefMode Enum Design
RefMode Semantics
NoneNullOnly-3(null) or-1(not null)TrackingKey Changes
Per-field RefMode determination based on:
None, Option →NullOnly, Rc/Arc →Tracking)#[fory(ref=false)]to disable tracking,#[fory(nullable)]for null supportPerformance optimization for non-trackable types:
if ref_mode != RefMode::Noneinstead of match for primitives/strings#[inline(always)]on hot pathsDescribe alternatives you've considered
nullable: bool,tracking: bool): More verbose, 4 combinations when only 3 are neededAdditional context
Go Reference Implementation
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 occurrenceFiles 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