Skip to main content

fory_core/
fory.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::buffer::{Reader, Writer};
19use crate::config::Config;
20use crate::ensure;
21use crate::error::Error;
22use crate::resolver::context::{ContextCache, ReadContext, WriteContext};
23use crate::resolver::type_resolver::TypeResolver;
24use crate::serializer::ForyDefault;
25use crate::serializer::{Serializer, StructSerializer};
26use crate::types::config_flags::{IS_CROSS_LANGUAGE_FLAG, IS_NULL_FLAG};
27use crate::types::{RefMode, SIZE_OF_REF_AND_TYPE};
28use std::cell::UnsafeCell;
29use std::mem;
30use std::sync::atomic::{AtomicU64, Ordering};
31use std::sync::OnceLock;
32
33/// Global counter to assign unique IDs to each Fory instance.
34static FORY_ID_COUNTER: AtomicU64 = AtomicU64::new(0);
35
36thread_local! {
37    /// Thread-local storage for WriteContext instances with fast path caching.
38    static WRITE_CONTEXTS: UnsafeCell<ContextCache<WriteContext<'static>>> =
39        UnsafeCell::new(ContextCache::new());
40
41    /// Thread-local storage for ReadContext instances with fast path caching.
42    static READ_CONTEXTS: UnsafeCell<ContextCache<ReadContext<'static>>> =
43        UnsafeCell::new(ContextCache::new());
44}
45
46/// The main Fory serialization framework instance.
47///
48/// `Fory` provides high-performance cross-language serialization and deserialization
49/// capabilities with support for multiple modes, reference tracking, and trait object serialization.
50///
51/// # Features
52///
53/// - **Cross-language serialization**: Serialize data in Rust and deserialize in other languages
54/// - **Multiple modes**: Schema-consistent and compatible serialization modes
55/// - **Reference tracking**: Handles shared and circular references
56/// - **Trait object serialization**: Supports serializing polymorphic trait objects
57/// - **Dynamic depth limiting**: Configurable limit for nested dynamic object serialization
58///
59/// # Examples
60///
61/// Basic usage:
62///
63/// ```rust, ignore
64/// use fory::Fory;
65/// use fory::ForyObject;
66///
67/// #[derive(ForyObject)]
68/// struct User {
69///     name: String,
70///     age: u32,
71/// }
72///
73/// let fory = Fory::default();
74/// let user = User { name: "Alice".to_string(), age: 30 };
75/// let bytes = fory.serialize(&user);
76/// let deserialized: User = fory.deserialize(&bytes).unwrap();
77/// ```
78///
79/// Custom configuration:
80///
81/// ```rust
82/// use fory_core::Fory;
83///
84/// let fory = Fory::default()
85///     .compatible(true)
86///     .compress_string(true)
87///     .max_dyn_depth(10);
88/// ```
89pub struct Fory {
90    /// Unique identifier for this Fory instance, used as key in thread-local context maps.
91    id: u64,
92    /// Configuration for serialization behavior.
93    config: Config,
94    type_resolver: TypeResolver,
95    /// Lazy-initialized final type resolver (thread-safe, one-time initialization).
96    final_type_resolver: OnceLock<Result<TypeResolver, Error>>,
97}
98
99impl Default for Fory {
100    fn default() -> Self {
101        Fory {
102            id: FORY_ID_COUNTER.fetch_add(1, Ordering::Relaxed),
103            config: Config::default(),
104            type_resolver: TypeResolver::default(),
105            final_type_resolver: OnceLock::new(),
106        }
107    }
108}
109
110impl Fory {
111    /// Sets the serialization compatible mode for this Fory instance.
112    ///
113    /// # Arguments
114    ///
115    /// * `compatible` - The serialization compatible mode to use. Options are:
116    ///   - `false`: Schema must be consistent between serialization and deserialization.
117    ///     No metadata is shared. This is the fastest mode.
118    ///   - true`: Supports schema evolution and type metadata sharing for better
119    ///     cross-version compatibility.
120    ///
121    /// # Returns
122    ///
123    /// Returns `self` for method chaining.
124    ///
125    /// # Note
126    ///
127    /// Setting the compatible mode also automatically configures the `share_meta` flag:
128    /// - `false` → `share_meta = false`
129    /// - true` → `share_meta = true`
130    ///
131    /// # Examples
132    ///
133    /// ```rust
134    /// use fory_core::Fory;
135    ///
136    /// let fory = Fory::default().compatible(true);
137    /// ```
138    pub fn compatible(mut self, compatible: bool) -> Self {
139        // Setting share_meta individually is not supported currently
140        self.config.share_meta = compatible;
141        self.config.compatible = compatible;
142        self.type_resolver.set_compatible(compatible);
143        if compatible {
144            self.config.check_struct_version = false;
145        }
146        self
147    }
148
149    /// Enables or disables cross-language serialization protocol.
150    ///
151    /// # Arguments
152    ///
153    /// * `xlang` - If `true`, uses the cross-language serialization format compatible with
154    ///   other Fory implementations (Java, Python, C++, etc.). If `false`, uses a Rust-only
155    ///   optimized format.
156    ///
157    /// # Returns
158    ///
159    /// Returns `self` for method chaining.
160    ///
161    /// # Default
162    ///
163    /// The default value is `false`.
164    ///
165    /// # Examples
166    ///
167    /// ```rust
168    /// use fory_core::Fory;
169    ///
170    /// // For cross-language use (default)
171    /// let fory = Fory::default().xlang(true);
172    ///
173    /// // For Rust-only optimization, this mode is faster and more compact since it avoids
174    /// // cross-language metadata and type system costs.
175    /// let fory = Fory::default().xlang(false);
176    /// ```
177    pub fn xlang(mut self, xlang: bool) -> Self {
178        self.config.xlang = xlang;
179        if !self.config.check_struct_version {
180            self.config.check_struct_version = !self.config.compatible;
181        }
182        self.type_resolver.set_xlang(xlang);
183        self
184    }
185
186    /// Enables or disables meta string compression.
187    ///
188    /// # Arguments
189    ///
190    /// * `compress_string` - If `true`, enables meta string compression to reduce serialized
191    ///   payload size by deduplicating and encoding frequently used strings (such as type names
192    ///   and field names). If `false`, strings are serialized without compression.
193    ///
194    /// # Returns
195    ///
196    /// Returns `self` for method chaining.
197    ///
198    /// # Default
199    ///
200    /// The default value is `false`.
201    ///
202    /// # Trade-offs
203    ///
204    /// - **Enabled**: Smaller payload size, slightly higher CPU overhead
205    /// - **Disabled**: Larger payload size, faster serialization/deserialization
206    ///
207    /// # Examples
208    ///
209    /// ```rust
210    /// use fory_core::Fory;
211    ///
212    /// let fory = Fory::default().compress_string(true);
213    /// ```
214    pub fn compress_string(mut self, compress_string: bool) -> Self {
215        self.config.compress_string = compress_string;
216        self
217    }
218
219    /// Enables or disables class version checking for schema consistency.
220    ///
221    /// # Arguments
222    ///
223    /// * `check_struct_version` - If `true`, enables class version checking to ensure
224    ///   schema consistency between serialization and deserialization. When enabled,
225    ///   a version hash computed from field types is written/read to detect schema mismatches.
226    ///   If `false`, no version checking is performed.
227    ///
228    /// # Returns
229    ///
230    /// Returns `self` for method chaining.
231    ///
232    /// # Default
233    ///
234    /// The default value is `false`.
235    ///
236    /// # Note
237    ///
238    /// This feature is only effective when `compatible` mode is `false`. In compatible mode,
239    /// schema evolution is supported and version checking is not needed.
240    ///
241    /// # Examples
242    ///
243    /// ```rust
244    /// use fory_core::Fory;
245    ///
246    /// let fory = Fory::default()
247    ///     .compatible(false)
248    ///     .check_struct_version(true);
249    /// ```
250    pub fn check_struct_version(mut self, check_struct_version: bool) -> Self {
251        if self.config.compatible && check_struct_version {
252            // ignore setting if compatible mode is on
253            return self;
254        }
255        self.config.check_struct_version = check_struct_version;
256        self
257    }
258
259    /// Enables or disables reference tracking for shared and circular references.
260    ///
261    /// # Arguments
262    ///
263    /// * `track_ref` - If `true`, enables reference tracking which allows
264    ///   preserving shared object references and circular references during
265    ///   serialization/deserialization.
266    ///
267    /// # Returns
268    ///
269    /// Returns `self` for method chaining.
270    ///
271    /// # Default
272    ///
273    /// The default value is `false`.
274    ///
275    /// # Examples
276    ///
277    /// ```rust
278    /// use fory_core::Fory;
279    ///
280    /// let fory = Fory::default().track_ref(true);
281    /// ```
282    pub fn track_ref(mut self, track_ref: bool) -> Self {
283        self.config.track_ref = track_ref;
284        self
285    }
286
287    /// Sets the maximum depth for nested dynamic object serialization.
288    ///
289    /// # Arguments
290    ///
291    /// * `max_dyn_depth` - The maximum nesting depth allowed for dynamically-typed objects
292    ///   (e.g., trait objects, boxed types). This prevents stack overflow from deeply nested
293    ///   structures in dynamic serialization scenarios.
294    ///
295    /// # Returns
296    ///
297    /// Returns `self` for method chaining.
298    ///
299    /// # Default
300    ///
301    /// The default value is `5`.
302    ///
303    /// # Behavior
304    ///
305    /// When the depth limit is exceeded during deserialization, an error is returned to prevent
306    /// potential stack overflow or infinite recursion.
307    ///
308    /// # Examples
309    ///
310    /// ```rust
311    /// use fory_core::Fory;
312    ///
313    /// // Allow deeper nesting for complex object graphs
314    /// let fory = Fory::default().max_dyn_depth(10);
315    ///
316    /// // Restrict nesting for safer deserialization
317    /// let fory = Fory::default().max_dyn_depth(3);
318    /// ```
319    pub fn max_dyn_depth(mut self, max_dyn_depth: u32) -> Self {
320        self.config.max_dyn_depth = max_dyn_depth;
321        self
322    }
323
324    /// Returns whether cross-language serialization is enabled.
325    pub fn is_xlang(&self) -> bool {
326        self.config.xlang
327    }
328
329    /// Returns the current serialization mode.
330    ///
331    /// # Returns
332    ///
333    /// `true` if the serialization mode is compatible, `false` otherwise`.
334    pub fn is_compatible(&self) -> bool {
335        self.config.compatible
336    }
337
338    /// Returns whether string compression is enabled.
339    ///
340    /// # Returns
341    ///
342    /// `true` if meta string compression is enabled, `false` otherwise.
343    pub fn is_compress_string(&self) -> bool {
344        self.config.compress_string
345    }
346
347    /// Returns whether metadata sharing is enabled.
348    ///
349    /// # Returns
350    ///
351    /// `true` if metadata sharing is enabled (automatically set based on mode), `false` otherwise.
352    pub fn is_share_meta(&self) -> bool {
353        self.config.share_meta
354    }
355
356    /// Returns the maximum depth for nested dynamic object serialization.
357    pub fn get_max_dyn_depth(&self) -> u32 {
358        self.config.max_dyn_depth
359    }
360
361    /// Returns whether class version checking is enabled.
362    ///
363    /// # Returns
364    ///
365    /// `true` if class version checking is enabled, `false` otherwise.
366    pub fn is_check_struct_version(&self) -> bool {
367        self.config.check_struct_version
368    }
369
370    /// Returns a reference to the configuration.
371    pub fn config(&self) -> &Config {
372        &self.config
373    }
374
375    /// Checks whether the final type resolver has already been initialized.
376    ///
377    /// If it has, further type registrations would be silently ignored (the frozen
378    /// snapshot is what serialize/deserialize actually use),so we fail fast with
379    /// a clear error instead.
380    ///
381    /// # errors
382    ///
383    /// returns [`Error::NotAllowed`] when the resolver snapshot has already been
384    /// built (i.e after the first `serialize` / `deserialize` call).
385    fn check_registration_allowed(&self) -> Result<(), Error> {
386        if self.final_type_resolver.get().is_some() {
387            return Err(Error::not_allowed(
388                "Type registration is not allowed after the first serialize/deserialize call. \
389                 The type resolver snapshot has already been finalized. \
390                 Please complete all type registrations before performing any serialization or deserialization.",
391            ));
392        }
393        Ok(())
394    }
395
396    /// Serializes a value of type `T` into a byte vector.
397    ///
398    /// # Type Parameters
399    ///
400    /// * `T` - The type of the value to serialize. Must implement `Serializer`.
401    ///
402    /// # Arguments
403    ///
404    /// * `record` - A reference to the value to serialize.
405    ///
406    /// # Returns
407    ///
408    /// A `Vec<u8>` containing the serialized data.
409    ///
410    /// # Examples
411    ///
412    /// ```rust, ignore
413    /// use fory::Fory;
414    /// use fory::ForyObject;
415    ///
416    /// #[derive(ForyObject)]
417    /// struct Point { x: i32, y: i32 }
418    ///
419    /// let fory = Fory::default();
420    /// let point = Point { x: 10, y: 20 };
421    /// let bytes = fory.serialize(&point);
422    /// ```
423    pub fn serialize<T: Serializer>(&self, record: &T) -> Result<Vec<u8>, Error> {
424        self.with_write_context(
425            |context| match self.serialize_with_context(record, context) {
426                Ok(_) => {
427                    let result = context.writer.dump();
428                    context.writer.reset();
429                    Ok(result)
430                }
431                Err(err) => {
432                    context.writer.reset();
433                    Err(err)
434                }
435            },
436        )
437    }
438
439    /// Serializes a value of type `T` into the provided byte buffer.
440    ///
441    /// The serialized data is appended to the end of the buffer by default.
442    /// To write from a specific position, resize the buffer before calling this method.
443    ///
444    /// # Type Parameters
445    ///
446    /// * `T` - The type of the value to serialize. Must implement `Serializer`.
447    ///
448    /// # Arguments
449    ///
450    /// * `buf` - A mutable reference to the byte buffer to append the serialized data to.
451    ///   The buffer will be resized as needed during serialization.
452    /// * `record` - A reference to the value to serialize.
453    ///
454    /// # Returns
455    ///
456    /// The number of bytes written to the buffer on success, or an error if serialization fails.
457    ///
458    /// # Notes
459    ///
460    /// - Multiple `serialize_to` calls to the same buffer will append data sequentially.
461    ///
462    /// # Examples
463    ///
464    /// Basic usage - appending to a buffer:
465    ///
466    /// ```rust, ignore
467    /// use fory_core::Fory;
468    /// use fory_derive::ForyObject;
469    ///
470    /// #[derive(ForyObject)]
471    /// struct Point {
472    ///     x: i32,
473    ///     y: i32,
474    /// }
475    ///
476    /// let fory = Fory::default();
477    /// let point = Point { x: 1, y: 2 };
478    ///
479    /// let mut buf = Vec::new();
480    /// let bytes_written = fory.serialize_to(&mut buf, &point).unwrap();
481    /// assert_eq!(bytes_written, buf.len());
482    /// ```
483    ///
484    /// Multiple serializations to the same buffer:
485    ///
486    /// ```rust, ignore
487    /// use fory_core::Fory;
488    /// use fory_derive::ForyObject;
489    ///
490    /// #[derive(ForyObject, PartialEq, Debug)]
491    /// struct Point {
492    ///     x: i32,
493    ///     y: i32,
494    /// }
495    ///
496    /// let fory = Fory::default();
497    /// let p1 = Point { x: 1, y: 2 };
498    /// let p2 = Point { x: -3, y: 4 };
499    ///
500    /// let mut buf = Vec::new();
501    ///
502    /// // First serialization
503    /// let len1 = fory.serialize_to(&mut buf, &p1).unwrap();
504    /// let offset1 = buf.len();
505    ///
506    /// // Second serialization - appends to existing data
507    /// let len2 = fory.serialize_to(&mut buf, &p2).unwrap();
508    /// let offset2 = buf.len();
509    ///
510    /// assert_eq!(offset1, len1);
511    /// assert_eq!(offset2, len1 + len2);
512    ///
513    /// // Deserialize both objects
514    /// let deserialized1: Point = fory.deserialize(&buf[0..offset1]).unwrap();
515    /// let deserialized2: Point = fory.deserialize(&buf[offset1..offset2]).unwrap();
516    /// assert_eq!(deserialized1, p1);
517    /// assert_eq!(deserialized2, p2);
518    /// ```
519    ///
520    /// Writing to a specific position using `resize`:
521    /// # Notes on `vec.resize()`
522    ///
523    /// When calling `vec.resize(n, 0)`, note that if `n` is smaller than the current length,
524    /// the buffer will be truncated (not shrunk in capacity). The capacity remains unchanged,
525    /// making subsequent writes efficient for buffer reuse patterns:
526    ///
527    /// ```rust, ignore
528    /// use fory_core::Fory;
529    /// use fory_derive::ForyObject;
530    ///
531    /// #[derive(ForyObject)]
532    /// struct Point {
533    ///     x: i32,
534    ///     y: i32,
535    /// }
536    ///
537    /// let fory = Fory::default();
538    /// let point = Point { x: 1, y: 2 };
539    ///
540    /// let mut buf = Vec::with_capacity(1024);
541    /// buf.resize(16, 0);  // Set length to 16 to append the write, capacity stays 1024
542    ///
543    /// let initial_capacity = buf.capacity();
544    /// fory.serialize_to(&mut buf, &point).unwrap();
545    ///
546    /// // Reset to smaller size to append the write - capacity unchanged
547    /// buf.resize(16, 0);
548    /// assert_eq!(buf.capacity(), initial_capacity);  // Capacity not shrunk
549    ///
550    /// // Reuse buffer efficiently without reallocation
551    /// fory.serialize_to(&mut buf, &point).unwrap();
552    /// assert_eq!(buf.capacity(), initial_capacity);  // Still no reallocation
553    /// ```
554    pub fn serialize_to<T: Serializer>(
555        &self,
556        buf: &mut Vec<u8>,
557        record: &T,
558    ) -> Result<usize, Error> {
559        let start = buf.len();
560        self.with_write_context(|context| {
561            // Context from thread-local would be 'static. but context hold the buffer through `writer` field,
562            // so we should make buffer live longer.
563            // After serializing, `detach_writer` will be called, the writer in context will be set to dangling pointer.
564            // So it's safe to make buf live to the end of this method.
565            let outlive_buffer = unsafe { mem::transmute::<&mut Vec<u8>, &mut Vec<u8>>(buf) };
566            context.attach_writer(Writer::from_buffer(outlive_buffer));
567            let result = self.serialize_with_context(record, context);
568            let written_size = context.writer.len() - start;
569            context.detach_writer();
570            match result {
571                Ok(_) => Ok(written_size),
572                Err(err) => Err(err),
573            }
574        })
575    }
576
577    /// Gets the final type resolver, building it lazily on first access.
578    #[inline(always)]
579    fn get_final_type_resolver(&self) -> Result<&TypeResolver, Error> {
580        let result = self
581            .final_type_resolver
582            .get_or_init(|| self.type_resolver.build_final_type_resolver());
583        result
584            .as_ref()
585            .map_err(|e| Error::type_error(format!("Failed to build type resolver: {}", e)))
586    }
587
588    /// Executes a closure with mutable access to a WriteContext for this Fory instance.
589    /// The context is stored in thread-local storage, eliminating all lock contention.
590    /// Uses fast path caching for O(1) access when using the same Fory instance repeatedly.
591    #[inline(always)]
592    fn with_write_context<R>(
593        &self,
594        f: impl FnOnce(&mut WriteContext) -> Result<R, Error>,
595    ) -> Result<R, Error> {
596        // SAFETY: Thread-local storage is only accessed from the current thread.
597        // We use UnsafeCell to avoid RefCell's runtime borrow checking overhead.
598        // The closure `f` does not recursively call with_write_context, so there's no aliasing.
599        WRITE_CONTEXTS.with(|cache| {
600            let cache = unsafe { &mut *cache.get() };
601            let id = self.id;
602            let config = self.config.clone();
603
604            let context = cache.get_or_insert_result(id, || {
605                // Only fetch type resolver when creating a new context
606                let type_resolver = self.get_final_type_resolver()?;
607                Ok(Box::new(WriteContext::new(type_resolver.clone(), config)))
608            })?;
609            f(context)
610        })
611    }
612
613    /// Serializes a value of type `T` into a byte vector.
614    #[inline(always)]
615    fn serialize_with_context<T: Serializer>(
616        &self,
617        record: &T,
618        context: &mut WriteContext,
619    ) -> Result<(), Error> {
620        let result = self.serialize_with_context_inner::<T>(record, context);
621        context.reset();
622        result
623    }
624
625    #[inline(always)]
626    fn serialize_with_context_inner<T: Serializer>(
627        &self,
628        record: &T,
629        context: &mut WriteContext,
630    ) -> Result<(), Error> {
631        let is_none = record.fory_is_none();
632        self.write_head::<T>(is_none, &mut context.writer);
633        if !is_none {
634            // Use RefMode based on config:
635            // - If track_ref is enabled, use RefMode::Tracking for the root object
636            // - Otherwise, use RefMode::NullOnly which writes NOT_NULL_VALUE_FLAG
637            let ref_mode = if self.config.track_ref {
638                RefMode::Tracking
639            } else {
640                RefMode::NullOnly
641            };
642            // TypeMeta is written inline during serialization (streaming protocol)
643            <T as Serializer>::fory_write(record, context, ref_mode, true, false)?;
644        }
645        Ok(())
646    }
647
648    /// Registers a struct type with a numeric type ID for serialization.
649    ///
650    /// # Type Parameters
651    ///
652    /// * `T` - The struct type to register. Must implement `StructSerializer`, `Serializer`, and `ForyDefault`.
653    ///
654    /// # Arguments
655    ///
656    /// * `id` - A unique numeric identifier for the type. This ID is used in the serialized format
657    ///   to identify the type during deserialization.
658    ///
659    /// # Panics
660    ///
661    /// May panic if the type ID conflicts with an already registered type.
662    ///
663    /// # Examples
664    ///
665    /// ```rust, ignore
666    /// use fory::Fory;
667    /// use fory::ForyObject;
668    ///
669    /// #[derive(ForyObject)]
670    /// struct User { name: String, age: u32 }
671    ///
672    /// let mut fory = Fory::default();
673    /// fory.register::<User>(100);
674    /// ```
675    pub fn register<T: 'static + StructSerializer + Serializer + ForyDefault>(
676        &mut self,
677        id: u32,
678    ) -> Result<(), Error> {
679        self.check_registration_allowed()?;
680        self.type_resolver.register_by_id::<T>(id)
681    }
682
683    /// Register a union type with a numeric type ID.
684    ///
685    /// This is intended for union-compatible enums generated by the compiler.
686    pub fn register_union<T: 'static + StructSerializer + Serializer + ForyDefault>(
687        &mut self,
688        id: u32,
689    ) -> Result<(), Error> {
690        self.check_registration_allowed()?;
691        self.type_resolver.register_union_by_id::<T>(id)
692    }
693
694    /// Registers a struct type with a namespace and type name for cross-language serialization.
695    ///
696    /// # Type Parameters
697    ///
698    /// * `T` - The struct type to register. Must implement `StructSerializer`, `Serializer`, and `ForyDefault`.
699    ///
700    /// # Arguments
701    ///
702    /// * `namespace` - The namespace or package name for the type (e.g., "com.example.types").
703    ///   Use an empty string for the default namespace.
704    /// * `type_name` - The name of the type (e.g., "User").
705    ///
706    /// # Notes
707    ///
708    /// This registration method is preferred for cross-language serialization as it uses
709    /// human-readable type identifiers instead of numeric IDs, which improves compatibility
710    /// across different language implementations.
711    ///
712    /// # Examples
713    ///
714    /// ```rust, ignore
715    /// use fory::Fory;
716    /// use fory::ForyObject;
717    ///
718    /// #[derive(ForyObject)]
719    /// struct User { name: String, age: u32 }
720    ///
721    /// let mut fory = Fory::default();
722    /// fory.register_by_namespace::<User>("com.example", "User");
723    /// ```
724    pub fn register_by_namespace<T: 'static + StructSerializer + Serializer + ForyDefault>(
725        &mut self,
726        namespace: &str,
727        type_name: &str,
728    ) -> Result<(), Error> {
729        self.check_registration_allowed()?;
730        self.type_resolver
731            .register_by_namespace::<T>(namespace, type_name)
732    }
733
734    /// Register a union type with namespace and type name.
735    ///
736    /// This is intended for union-compatible enums generated by the compiler.
737    pub fn register_union_by_namespace<T: 'static + StructSerializer + Serializer + ForyDefault>(
738        &mut self,
739        namespace: &str,
740        type_name: &str,
741    ) -> Result<(), Error> {
742        self.check_registration_allowed()?;
743        self.type_resolver
744            .register_union_by_namespace::<T>(namespace, type_name)
745    }
746
747    /// Registers a struct type with a type name (using the default namespace).
748    ///
749    /// # Type Parameters
750    ///
751    /// * `T` - The struct type to register. Must implement `StructSerializer`, `Serializer`, and `ForyDefault`.
752    ///
753    /// # Arguments
754    ///
755    /// * `type_name` - The name of the type (e.g., "User").
756    ///
757    /// # Notes
758    ///
759    /// This is a convenience method that calls `register_by_namespace` with an empty namespace string.
760    ///
761    /// # Examples
762    ///
763    /// ```rust, ignore
764    /// use fory::Fory;
765    /// use fory::ForyObject;
766    ///
767    /// #[derive(ForyObject)]
768    /// struct User { name: String, age: u32 }
769    ///
770    /// let mut fory = Fory::default();
771    /// fory.register_by_name::<User>("User");
772    /// ```
773    pub fn register_by_name<T: 'static + StructSerializer + Serializer + ForyDefault>(
774        &mut self,
775        type_name: &str,
776    ) -> Result<(), Error> {
777        self.check_registration_allowed()?;
778        self.register_by_namespace::<T>("", type_name)
779    }
780
781    /// Register a union type with type name only (no namespace).
782    pub fn register_union_by_name<T: 'static + StructSerializer + Serializer + ForyDefault>(
783        &mut self,
784        type_name: &str,
785    ) -> Result<(), Error> {
786        self.check_registration_allowed()?;
787        self.register_union_by_namespace::<T>("", type_name)
788    }
789
790    /// Registers a custom serializer type with a numeric type ID.
791    ///
792    /// # Type Parameters
793    ///
794    /// * `T` - The type to register. Must implement `Serializer` and `ForyDefault`.
795    ///   Unlike `register()`, this does not require `StructSerializer`, making it suitable
796    ///   for non-struct types or types with custom serialization logic.
797    ///
798    /// # Arguments
799    ///
800    /// * `id` - A unique numeric identifier for the type.
801    ///
802    /// # Use Cases
803    ///
804    /// Use this method to register:
805    /// - Enum types with custom serialization
806    /// - Wrapper types
807    /// - Types with hand-written `Serializer` implementations
808    ///
809    /// # Examples
810    ///
811    /// ```rust, ignore
812    /// use fory_core::Fory;
813    ///
814    /// let mut fory = Fory::default();
815    /// fory.register_serializer::<MyCustomType>(200);
816    /// ```
817    pub fn register_serializer<T: Serializer + ForyDefault>(
818        &mut self,
819        id: u32,
820    ) -> Result<(), Error> {
821        self.check_registration_allowed()?;
822        self.type_resolver.register_serializer_by_id::<T>(id)
823    }
824
825    /// Registers a custom serializer type with a namespace and type name.
826    ///
827    /// # Type Parameters
828    ///
829    /// * `T` - The type to register. Must implement `Serializer` and `ForyDefault`.
830    ///
831    /// # Arguments
832    ///
833    /// * `namespace` - The namespace or package name for the type.
834    /// * `type_name` - The name of the type.
835    ///
836    /// # Notes
837    ///
838    /// This is the namespace-based equivalent of `register_serializer()`, preferred for
839    /// cross-language serialization scenarios.
840    ///
841    pub fn register_serializer_by_namespace<T: Serializer + ForyDefault>(
842        &mut self,
843        namespace: &str,
844        type_name: &str,
845    ) -> Result<(), Error> {
846        self.check_registration_allowed()?;
847        self.type_resolver
848            .register_serializer_by_namespace::<T>(namespace, type_name)
849    }
850
851    /// Registers a custom serializer type with a type name (using the default namespace).
852    ///
853    /// # Type Parameters
854    ///
855    /// * `T` - The type to register. Must implement `Serializer` and `ForyDefault`.
856    ///
857    /// # Arguments
858    ///
859    /// * `type_name` - The name of the type.
860    ///
861    /// # Notes
862    ///
863    /// This is a convenience method that calls `register_serializer_by_namespace` with an empty namespace.
864    pub fn register_serializer_by_name<T: Serializer + ForyDefault>(
865        &mut self,
866        type_name: &str,
867    ) -> Result<(), Error> {
868        self.check_registration_allowed()?;
869        self.register_serializer_by_namespace::<T>("", type_name)
870    }
871
872    /// Registers a generic trait object type for serialization.
873    /// This method should be used to register collection types such as `Vec<T>`, `HashMap<K, V>`, etc.
874    /// Don't register concrete struct types with this method. Use `register()` instead.
875    pub fn register_generic_trait<T: 'static + Serializer + ForyDefault>(
876        &mut self,
877    ) -> Result<(), Error> {
878        self.check_registration_allowed()?;
879        self.type_resolver.register_generic_trait::<T>()
880    }
881
882    /// Writes the serialization header to the writer.
883    #[inline(always)]
884    pub fn write_head<T: Serializer>(&self, is_none: bool, writer: &mut Writer) {
885        const HEAD_SIZE: usize = 10;
886        writer.reserve(T::fory_reserved_space() + SIZE_OF_REF_AND_TYPE + HEAD_SIZE);
887        let mut bitmap: u8 = 0;
888        if self.config.xlang {
889            bitmap |= IS_CROSS_LANGUAGE_FLAG;
890        }
891        if is_none {
892            bitmap |= IS_NULL_FLAG;
893        }
894        writer.write_u8(bitmap);
895    }
896
897    /// Deserializes data from a byte slice into a value of type `T`.
898    ///
899    /// # Type Parameters
900    ///
901    /// * `T` - The target type to deserialize into. Must implement `Serializer` and `ForyDefault`.
902    ///
903    /// # Arguments
904    ///
905    /// * `bf` - The byte slice containing the serialized data.
906    ///
907    /// # Returns
908    ///
909    /// * `Ok(T)` - The deserialized value on success.
910    /// * `Err(Error)` - An error if deserialization fails (e.g., invalid format, type mismatch).
911    ///
912    /// # Panics
913    ///
914    /// Panics in debug mode if there are unread bytes remaining after successful deserialization,
915    /// indicating a potential protocol violation.
916    ///
917    /// # Examples
918    ///
919    /// ```rust, ignore
920    /// use fory::Fory;
921    /// use fory::ForyObject;
922    ///
923    /// #[derive(ForyObject)]
924    /// struct Point { x: i32, y: i32 }
925    ///
926    /// let fory = Fory::default();
927    /// let point = Point { x: 10, y: 20 };
928    /// let bytes = fory.serialize(&point);
929    /// let deserialized: Point = fory.deserialize(&bytes).unwrap();
930    /// ```
931    pub fn deserialize<T: Serializer + ForyDefault>(&self, bf: &[u8]) -> Result<T, Error> {
932        self.with_read_context(|context| {
933            let outlive_buffer = unsafe { mem::transmute::<&[u8], &[u8]>(bf) };
934            context.attach_reader(Reader::new(outlive_buffer));
935            let result = self.deserialize_with_context(context);
936            context.detach_reader();
937            result
938        })
939    }
940
941    /// Deserializes data from a `Reader` into a value of type `T`.
942    ///
943    /// This method is the paired read operation for [`serialize_to`](Self::serialize_to).
944    /// It reads serialized data from the current position of the reader and automatically
945    /// advances the cursor to the end of the read data, making it suitable for reading
946    /// multiple objects sequentially from the same buffer.
947    ///
948    /// # Type Parameters
949    ///
950    /// * `T` - The target type to deserialize into. Must implement `Serializer` and `ForyDefault`.
951    ///
952    /// # Arguments
953    ///
954    /// * `reader` - A mutable reference to the `Reader` containing the serialized data.
955    ///   The reader's cursor will be advanced to the end of the deserialized data.
956    ///
957    /// # Returns
958    ///
959    /// * `Ok(T)` - The deserialized value on success.
960    /// * `Err(Error)` - An error if deserialization fails (e.g., invalid format, type mismatch).
961    ///
962    /// # Notes
963    ///
964    /// - The reader's cursor is automatically updated after each successful read.
965    /// - This method is ideal for reading multiple objects from the same buffer sequentially.
966    /// - See [`serialize_to`](Self::serialize_to) for complete usage examples.
967    ///
968    /// # Examples
969    ///
970    /// Basic usage:
971    ///
972    /// ```rust, ignore
973    /// use fory_core::{Fory, Reader};
974    /// use fory_derive::ForyObject;
975    ///
976    /// #[derive(ForyObject)]
977    /// struct Point { x: i32, y: i32 }
978    ///
979    /// let fory = Fory::default();
980    /// let point = Point { x: 10, y: 20 };
981    ///
982    /// let mut buf = Vec::new();
983    /// fory.serialize_to(&point, &mut buf).unwrap();
984    ///
985    /// let mut reader = Reader::new(&buf);
986    /// let deserialized: Point = fory.deserialize_from(&mut reader).unwrap();
987    /// ```
988    pub fn deserialize_from<T: Serializer + ForyDefault>(
989        &self,
990        reader: &mut Reader,
991    ) -> Result<T, Error> {
992        self.with_read_context(|context| {
993            let outlive_buffer = unsafe { mem::transmute::<&[u8], &[u8]>(reader.bf) };
994            let mut new_reader = Reader::new(outlive_buffer);
995            new_reader.set_cursor(reader.cursor);
996            context.attach_reader(new_reader);
997            let result = self.deserialize_with_context(context);
998            let end = context.detach_reader().get_cursor();
999            reader.set_cursor(end);
1000            result
1001        })
1002    }
1003
1004    /// Executes a closure with mutable access to a ReadContext for this Fory instance.
1005    /// The context is stored in thread-local storage, eliminating all lock contention.
1006    /// Uses fast path caching for O(1) access when using the same Fory instance repeatedly.
1007    #[inline(always)]
1008    fn with_read_context<R>(
1009        &self,
1010        f: impl FnOnce(&mut ReadContext) -> Result<R, Error>,
1011    ) -> Result<R, Error> {
1012        // SAFETY: Thread-local storage is only accessed from the current thread.
1013        // We use UnsafeCell to avoid RefCell's runtime borrow checking overhead.
1014        // The closure `f` does not recursively call with_read_context, so there's no aliasing.
1015        READ_CONTEXTS.with(|cache| {
1016            let cache = unsafe { &mut *cache.get() };
1017            let id = self.id;
1018            let config = self.config.clone();
1019
1020            let context = cache.get_or_insert_result(id, || {
1021                // Only fetch type resolver when creating a new context
1022                let type_resolver = self.get_final_type_resolver()?;
1023                Ok(Box::new(ReadContext::new(type_resolver.clone(), config)))
1024            })?;
1025            f(context)
1026        })
1027    }
1028
1029    #[inline(always)]
1030    fn deserialize_with_context<T: Serializer + ForyDefault>(
1031        &self,
1032        context: &mut ReadContext,
1033    ) -> Result<T, Error> {
1034        let result = self.deserialize_with_context_inner::<T>(context);
1035        context.reset();
1036        result
1037    }
1038
1039    #[inline(always)]
1040    fn deserialize_with_context_inner<T: Serializer + ForyDefault>(
1041        &self,
1042        context: &mut ReadContext,
1043    ) -> Result<T, Error> {
1044        let is_none = self.read_head(&mut context.reader)?;
1045        if is_none {
1046            return Ok(T::fory_default());
1047        }
1048        // Use RefMode based on config:
1049        // - If track_ref is enabled, use RefMode::Tracking for the root object
1050        // - Otherwise, use RefMode::NullOnly
1051        let ref_mode = if self.config.track_ref {
1052            RefMode::Tracking
1053        } else {
1054            RefMode::NullOnly
1055        };
1056        // TypeMeta is read inline during deserialization (streaming protocol)
1057        let result = <T as Serializer>::fory_read(context, ref_mode, true);
1058        context.ref_reader.resolve_callbacks();
1059        result
1060    }
1061
1062    #[inline(always)]
1063    fn read_head(&self, reader: &mut Reader) -> Result<bool, Error> {
1064        let bitmap = reader.read_u8()?;
1065        let peer_is_xlang = (bitmap & IS_CROSS_LANGUAGE_FLAG) != 0;
1066        ensure!(
1067            self.config.xlang == peer_is_xlang,
1068            Error::invalid_data("header bitmap mismatch at xlang bit")
1069        );
1070        let is_none = (bitmap & IS_NULL_FLAG) != 0;
1071        if is_none {
1072            return Ok(true);
1073        }
1074        Ok(false)
1075    }
1076}