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    /// Serializes a value of type `T` into a byte vector.
376    ///
377    /// # Type Parameters
378    ///
379    /// * `T` - The type of the value to serialize. Must implement `Serializer`.
380    ///
381    /// # Arguments
382    ///
383    /// * `record` - A reference to the value to serialize.
384    ///
385    /// # Returns
386    ///
387    /// A `Vec<u8>` containing the serialized data.
388    ///
389    /// # Examples
390    ///
391    /// ```rust, ignore
392    /// use fory::Fory;
393    /// use fory::ForyObject;
394    ///
395    /// #[derive(ForyObject)]
396    /// struct Point { x: i32, y: i32 }
397    ///
398    /// let fory = Fory::default();
399    /// let point = Point { x: 10, y: 20 };
400    /// let bytes = fory.serialize(&point);
401    /// ```
402    pub fn serialize<T: Serializer>(&self, record: &T) -> Result<Vec<u8>, Error> {
403        self.with_write_context(
404            |context| match self.serialize_with_context(record, context) {
405                Ok(_) => {
406                    let result = context.writer.dump();
407                    context.writer.reset();
408                    Ok(result)
409                }
410                Err(err) => {
411                    context.writer.reset();
412                    Err(err)
413                }
414            },
415        )
416    }
417
418    /// Serializes a value of type `T` into the provided byte buffer.
419    ///
420    /// The serialized data is appended to the end of the buffer by default.
421    /// To write from a specific position, resize the buffer before calling this method.
422    ///
423    /// # Type Parameters
424    ///
425    /// * `T` - The type of the value to serialize. Must implement `Serializer`.
426    ///
427    /// # Arguments
428    ///
429    /// * `buf` - A mutable reference to the byte buffer to append the serialized data to.
430    ///   The buffer will be resized as needed during serialization.
431    /// * `record` - A reference to the value to serialize.
432    ///
433    /// # Returns
434    ///
435    /// The number of bytes written to the buffer on success, or an error if serialization fails.
436    ///
437    /// # Notes
438    ///
439    /// - Multiple `serialize_to` calls to the same buffer will append data sequentially.
440    ///
441    /// # Examples
442    ///
443    /// Basic usage - appending to a buffer:
444    ///
445    /// ```rust, ignore
446    /// use fory_core::Fory;
447    /// use fory_derive::ForyObject;
448    ///
449    /// #[derive(ForyObject)]
450    /// struct Point {
451    ///     x: i32,
452    ///     y: i32,
453    /// }
454    ///
455    /// let fory = Fory::default();
456    /// let point = Point { x: 1, y: 2 };
457    ///
458    /// let mut buf = Vec::new();
459    /// let bytes_written = fory.serialize_to(&mut buf, &point).unwrap();
460    /// assert_eq!(bytes_written, buf.len());
461    /// ```
462    ///
463    /// Multiple serializations to the same buffer:
464    ///
465    /// ```rust, ignore
466    /// use fory_core::Fory;
467    /// use fory_derive::ForyObject;
468    ///
469    /// #[derive(ForyObject, PartialEq, Debug)]
470    /// struct Point {
471    ///     x: i32,
472    ///     y: i32,
473    /// }
474    ///
475    /// let fory = Fory::default();
476    /// let p1 = Point { x: 1, y: 2 };
477    /// let p2 = Point { x: -3, y: 4 };
478    ///
479    /// let mut buf = Vec::new();
480    ///
481    /// // First serialization
482    /// let len1 = fory.serialize_to(&mut buf, &p1).unwrap();
483    /// let offset1 = buf.len();
484    ///
485    /// // Second serialization - appends to existing data
486    /// let len2 = fory.serialize_to(&mut buf, &p2).unwrap();
487    /// let offset2 = buf.len();
488    ///
489    /// assert_eq!(offset1, len1);
490    /// assert_eq!(offset2, len1 + len2);
491    ///
492    /// // Deserialize both objects
493    /// let deserialized1: Point = fory.deserialize(&buf[0..offset1]).unwrap();
494    /// let deserialized2: Point = fory.deserialize(&buf[offset1..offset2]).unwrap();
495    /// assert_eq!(deserialized1, p1);
496    /// assert_eq!(deserialized2, p2);
497    /// ```
498    ///
499    /// Writing to a specific position using `resize`:
500    /// # Notes on `vec.resize()`
501    ///
502    /// When calling `vec.resize(n, 0)`, note that if `n` is smaller than the current length,
503    /// the buffer will be truncated (not shrunk in capacity). The capacity remains unchanged,
504    /// making subsequent writes efficient for buffer reuse patterns:
505    ///
506    /// ```rust, ignore
507    /// use fory_core::Fory;
508    /// use fory_derive::ForyObject;
509    ///
510    /// #[derive(ForyObject)]
511    /// struct Point {
512    ///     x: i32,
513    ///     y: i32,
514    /// }
515    ///
516    /// let fory = Fory::default();
517    /// let point = Point { x: 1, y: 2 };
518    ///
519    /// let mut buf = Vec::with_capacity(1024);
520    /// buf.resize(16, 0);  // Set length to 16 to append the write, capacity stays 1024
521    ///
522    /// let initial_capacity = buf.capacity();
523    /// fory.serialize_to(&mut buf, &point).unwrap();
524    ///
525    /// // Reset to smaller size to append the write - capacity unchanged
526    /// buf.resize(16, 0);
527    /// assert_eq!(buf.capacity(), initial_capacity);  // Capacity not shrunk
528    ///
529    /// // Reuse buffer efficiently without reallocation
530    /// fory.serialize_to(&mut buf, &point).unwrap();
531    /// assert_eq!(buf.capacity(), initial_capacity);  // Still no reallocation
532    /// ```
533    pub fn serialize_to<T: Serializer>(
534        &self,
535        buf: &mut Vec<u8>,
536        record: &T,
537    ) -> Result<usize, Error> {
538        let start = buf.len();
539        self.with_write_context(|context| {
540            // Context from thread-local would be 'static. but context hold the buffer through `writer` field,
541            // so we should make buffer live longer.
542            // After serializing, `detach_writer` will be called, the writer in context will be set to dangling pointer.
543            // So it's safe to make buf live to the end of this method.
544            let outlive_buffer = unsafe { mem::transmute::<&mut Vec<u8>, &mut Vec<u8>>(buf) };
545            context.attach_writer(Writer::from_buffer(outlive_buffer));
546            let result = self.serialize_with_context(record, context);
547            let written_size = context.writer.len() - start;
548            context.detach_writer();
549            match result {
550                Ok(_) => Ok(written_size),
551                Err(err) => Err(err),
552            }
553        })
554    }
555
556    /// Gets the final type resolver, building it lazily on first access.
557    #[inline(always)]
558    fn get_final_type_resolver(&self) -> Result<&TypeResolver, Error> {
559        let result = self
560            .final_type_resolver
561            .get_or_init(|| self.type_resolver.build_final_type_resolver());
562        result
563            .as_ref()
564            .map_err(|e| Error::type_error(format!("Failed to build type resolver: {}", e)))
565    }
566
567    /// Executes a closure with mutable access to a WriteContext for this Fory instance.
568    /// The context is stored in thread-local storage, eliminating all lock contention.
569    /// Uses fast path caching for O(1) access when using the same Fory instance repeatedly.
570    #[inline(always)]
571    fn with_write_context<R>(
572        &self,
573        f: impl FnOnce(&mut WriteContext) -> Result<R, Error>,
574    ) -> Result<R, Error> {
575        // SAFETY: Thread-local storage is only accessed from the current thread.
576        // We use UnsafeCell to avoid RefCell's runtime borrow checking overhead.
577        // The closure `f` does not recursively call with_write_context, so there's no aliasing.
578        WRITE_CONTEXTS.with(|cache| {
579            let cache = unsafe { &mut *cache.get() };
580            let id = self.id;
581            let config = self.config.clone();
582
583            let context = cache.get_or_insert_result(id, || {
584                // Only fetch type resolver when creating a new context
585                let type_resolver = self.get_final_type_resolver()?;
586                Ok(Box::new(WriteContext::new(type_resolver.clone(), config)))
587            })?;
588            f(context)
589        })
590    }
591
592    /// Serializes a value of type `T` into a byte vector.
593    #[inline(always)]
594    fn serialize_with_context<T: Serializer>(
595        &self,
596        record: &T,
597        context: &mut WriteContext,
598    ) -> Result<(), Error> {
599        let result = self.serialize_with_context_inner::<T>(record, context);
600        context.reset();
601        result
602    }
603
604    #[inline(always)]
605    fn serialize_with_context_inner<T: Serializer>(
606        &self,
607        record: &T,
608        context: &mut WriteContext,
609    ) -> Result<(), Error> {
610        let is_none = record.fory_is_none();
611        self.write_head::<T>(is_none, &mut context.writer);
612        if !is_none {
613            // Use RefMode based on config:
614            // - If track_ref is enabled, use RefMode::Tracking for the root object
615            // - Otherwise, use RefMode::NullOnly which writes NOT_NULL_VALUE_FLAG
616            let ref_mode = if self.config.track_ref {
617                RefMode::Tracking
618            } else {
619                RefMode::NullOnly
620            };
621            // TypeMeta is written inline during serialization (streaming protocol)
622            <T as Serializer>::fory_write(record, context, ref_mode, true, false)?;
623        }
624        Ok(())
625    }
626
627    /// Registers a struct type with a numeric type ID for serialization.
628    ///
629    /// # Type Parameters
630    ///
631    /// * `T` - The struct type to register. Must implement `StructSerializer`, `Serializer`, and `ForyDefault`.
632    ///
633    /// # Arguments
634    ///
635    /// * `id` - A unique numeric identifier for the type. This ID is used in the serialized format
636    ///   to identify the type during deserialization.
637    ///
638    /// # Panics
639    ///
640    /// May panic if the type ID conflicts with an already registered type.
641    ///
642    /// # Examples
643    ///
644    /// ```rust, ignore
645    /// use fory::Fory;
646    /// use fory::ForyObject;
647    ///
648    /// #[derive(ForyObject)]
649    /// struct User { name: String, age: u32 }
650    ///
651    /// let mut fory = Fory::default();
652    /// fory.register::<User>(100);
653    /// ```
654    pub fn register<T: 'static + StructSerializer + Serializer + ForyDefault>(
655        &mut self,
656        id: u32,
657    ) -> Result<(), Error> {
658        self.type_resolver.register_by_id::<T>(id)
659    }
660
661    /// Register a union type with a numeric type ID.
662    ///
663    /// This is intended for union-compatible enums generated by the compiler.
664    pub fn register_union<T: 'static + StructSerializer + Serializer + ForyDefault>(
665        &mut self,
666        id: u32,
667    ) -> Result<(), Error> {
668        self.type_resolver.register_union_by_id::<T>(id)
669    }
670
671    /// Registers a struct type with a namespace and type name for cross-language serialization.
672    ///
673    /// # Type Parameters
674    ///
675    /// * `T` - The struct type to register. Must implement `StructSerializer`, `Serializer`, and `ForyDefault`.
676    ///
677    /// # Arguments
678    ///
679    /// * `namespace` - The namespace or package name for the type (e.g., "com.example.types").
680    ///   Use an empty string for the default namespace.
681    /// * `type_name` - The name of the type (e.g., "User").
682    ///
683    /// # Notes
684    ///
685    /// This registration method is preferred for cross-language serialization as it uses
686    /// human-readable type identifiers instead of numeric IDs, which improves compatibility
687    /// across different language implementations.
688    ///
689    /// # Examples
690    ///
691    /// ```rust, ignore
692    /// use fory::Fory;
693    /// use fory::ForyObject;
694    ///
695    /// #[derive(ForyObject)]
696    /// struct User { name: String, age: u32 }
697    ///
698    /// let mut fory = Fory::default();
699    /// fory.register_by_namespace::<User>("com.example", "User");
700    /// ```
701    pub fn register_by_namespace<T: 'static + StructSerializer + Serializer + ForyDefault>(
702        &mut self,
703        namespace: &str,
704        type_name: &str,
705    ) -> Result<(), Error> {
706        self.type_resolver
707            .register_by_namespace::<T>(namespace, type_name)
708    }
709
710    /// Register a union type with namespace and type name.
711    ///
712    /// This is intended for union-compatible enums generated by the compiler.
713    pub fn register_union_by_namespace<T: 'static + StructSerializer + Serializer + ForyDefault>(
714        &mut self,
715        namespace: &str,
716        type_name: &str,
717    ) -> Result<(), Error> {
718        self.type_resolver
719            .register_union_by_namespace::<T>(namespace, type_name)
720    }
721
722    /// Registers a struct type with a type name (using the default namespace).
723    ///
724    /// # Type Parameters
725    ///
726    /// * `T` - The struct type to register. Must implement `StructSerializer`, `Serializer`, and `ForyDefault`.
727    ///
728    /// # Arguments
729    ///
730    /// * `type_name` - The name of the type (e.g., "User").
731    ///
732    /// # Notes
733    ///
734    /// This is a convenience method that calls `register_by_namespace` with an empty namespace string.
735    ///
736    /// # Examples
737    ///
738    /// ```rust, ignore
739    /// use fory::Fory;
740    /// use fory::ForyObject;
741    ///
742    /// #[derive(ForyObject)]
743    /// struct User { name: String, age: u32 }
744    ///
745    /// let mut fory = Fory::default();
746    /// fory.register_by_name::<User>("User");
747    /// ```
748    pub fn register_by_name<T: 'static + StructSerializer + Serializer + ForyDefault>(
749        &mut self,
750        type_name: &str,
751    ) -> Result<(), Error> {
752        self.register_by_namespace::<T>("", type_name)
753    }
754
755    /// Register a union type with type name only (no namespace).
756    pub fn register_union_by_name<T: 'static + StructSerializer + Serializer + ForyDefault>(
757        &mut self,
758        type_name: &str,
759    ) -> Result<(), Error> {
760        self.register_union_by_namespace::<T>("", type_name)
761    }
762
763    /// Registers a custom serializer type with a numeric type ID.
764    ///
765    /// # Type Parameters
766    ///
767    /// * `T` - The type to register. Must implement `Serializer` and `ForyDefault`.
768    ///   Unlike `register()`, this does not require `StructSerializer`, making it suitable
769    ///   for non-struct types or types with custom serialization logic.
770    ///
771    /// # Arguments
772    ///
773    /// * `id` - A unique numeric identifier for the type.
774    ///
775    /// # Use Cases
776    ///
777    /// Use this method to register:
778    /// - Enum types with custom serialization
779    /// - Wrapper types
780    /// - Types with hand-written `Serializer` implementations
781    ///
782    /// # Examples
783    ///
784    /// ```rust, ignore
785    /// use fory_core::Fory;
786    ///
787    /// let mut fory = Fory::default();
788    /// fory.register_serializer::<MyCustomType>(200);
789    /// ```
790    pub fn register_serializer<T: Serializer + ForyDefault>(
791        &mut self,
792        id: u32,
793    ) -> Result<(), Error> {
794        self.type_resolver.register_serializer_by_id::<T>(id)
795    }
796
797    /// Registers a custom serializer type with a namespace and type name.
798    ///
799    /// # Type Parameters
800    ///
801    /// * `T` - The type to register. Must implement `Serializer` and `ForyDefault`.
802    ///
803    /// # Arguments
804    ///
805    /// * `namespace` - The namespace or package name for the type.
806    /// * `type_name` - The name of the type.
807    ///
808    /// # Notes
809    ///
810    /// This is the namespace-based equivalent of `register_serializer()`, preferred for
811    /// cross-language serialization scenarios.
812    ///
813    pub fn register_serializer_by_namespace<T: Serializer + ForyDefault>(
814        &mut self,
815        namespace: &str,
816        type_name: &str,
817    ) -> Result<(), Error> {
818        self.type_resolver
819            .register_serializer_by_namespace::<T>(namespace, type_name)
820    }
821
822    /// Registers a custom serializer type with a type name (using the default namespace).
823    ///
824    /// # Type Parameters
825    ///
826    /// * `T` - The type to register. Must implement `Serializer` and `ForyDefault`.
827    ///
828    /// # Arguments
829    ///
830    /// * `type_name` - The name of the type.
831    ///
832    /// # Notes
833    ///
834    /// This is a convenience method that calls `register_serializer_by_namespace` with an empty namespace.
835    pub fn register_serializer_by_name<T: Serializer + ForyDefault>(
836        &mut self,
837        type_name: &str,
838    ) -> Result<(), Error> {
839        self.register_serializer_by_namespace::<T>("", type_name)
840    }
841
842    /// Registers a generic trait object type for serialization.
843    /// This method should be used to register collection types such as `Vec<T>`, `HashMap<K, V>`, etc.
844    /// Don't register concrete struct types with this method. Use `register()` instead.
845    pub fn register_generic_trait<T: 'static + Serializer + ForyDefault>(
846        &mut self,
847    ) -> Result<(), Error> {
848        self.type_resolver.register_generic_trait::<T>()
849    }
850
851    /// Writes the serialization header to the writer.
852    #[inline(always)]
853    pub fn write_head<T: Serializer>(&self, is_none: bool, writer: &mut Writer) {
854        const HEAD_SIZE: usize = 10;
855        writer.reserve(T::fory_reserved_space() + SIZE_OF_REF_AND_TYPE + HEAD_SIZE);
856        let mut bitmap: u8 = 0;
857        if self.config.xlang {
858            bitmap |= IS_CROSS_LANGUAGE_FLAG;
859        }
860        if is_none {
861            bitmap |= IS_NULL_FLAG;
862        }
863        writer.write_u8(bitmap);
864    }
865
866    /// Deserializes data from a byte slice into a value of type `T`.
867    ///
868    /// # Type Parameters
869    ///
870    /// * `T` - The target type to deserialize into. Must implement `Serializer` and `ForyDefault`.
871    ///
872    /// # Arguments
873    ///
874    /// * `bf` - The byte slice containing the serialized data.
875    ///
876    /// # Returns
877    ///
878    /// * `Ok(T)` - The deserialized value on success.
879    /// * `Err(Error)` - An error if deserialization fails (e.g., invalid format, type mismatch).
880    ///
881    /// # Panics
882    ///
883    /// Panics in debug mode if there are unread bytes remaining after successful deserialization,
884    /// indicating a potential protocol violation.
885    ///
886    /// # Examples
887    ///
888    /// ```rust, ignore
889    /// use fory::Fory;
890    /// use fory::ForyObject;
891    ///
892    /// #[derive(ForyObject)]
893    /// struct Point { x: i32, y: i32 }
894    ///
895    /// let fory = Fory::default();
896    /// let point = Point { x: 10, y: 20 };
897    /// let bytes = fory.serialize(&point);
898    /// let deserialized: Point = fory.deserialize(&bytes).unwrap();
899    /// ```
900    pub fn deserialize<T: Serializer + ForyDefault>(&self, bf: &[u8]) -> Result<T, Error> {
901        self.with_read_context(|context| {
902            let outlive_buffer = unsafe { mem::transmute::<&[u8], &[u8]>(bf) };
903            context.attach_reader(Reader::new(outlive_buffer));
904            let result = self.deserialize_with_context(context);
905            context.detach_reader();
906            result
907        })
908    }
909
910    /// Deserializes data from a `Reader` into a value of type `T`.
911    ///
912    /// This method is the paired read operation for [`serialize_to`](Self::serialize_to).
913    /// It reads serialized data from the current position of the reader and automatically
914    /// advances the cursor to the end of the read data, making it suitable for reading
915    /// multiple objects sequentially from the same buffer.
916    ///
917    /// # Type Parameters
918    ///
919    /// * `T` - The target type to deserialize into. Must implement `Serializer` and `ForyDefault`.
920    ///
921    /// # Arguments
922    ///
923    /// * `reader` - A mutable reference to the `Reader` containing the serialized data.
924    ///   The reader's cursor will be advanced to the end of the deserialized data.
925    ///
926    /// # Returns
927    ///
928    /// * `Ok(T)` - The deserialized value on success.
929    /// * `Err(Error)` - An error if deserialization fails (e.g., invalid format, type mismatch).
930    ///
931    /// # Notes
932    ///
933    /// - The reader's cursor is automatically updated after each successful read.
934    /// - This method is ideal for reading multiple objects from the same buffer sequentially.
935    /// - See [`serialize_to`](Self::serialize_to) for complete usage examples.
936    ///
937    /// # Examples
938    ///
939    /// Basic usage:
940    ///
941    /// ```rust, ignore
942    /// use fory_core::{Fory, Reader};
943    /// use fory_derive::ForyObject;
944    ///
945    /// #[derive(ForyObject)]
946    /// struct Point { x: i32, y: i32 }
947    ///
948    /// let fory = Fory::default();
949    /// let point = Point { x: 10, y: 20 };
950    ///
951    /// let mut buf = Vec::new();
952    /// fory.serialize_to(&point, &mut buf).unwrap();
953    ///
954    /// let mut reader = Reader::new(&buf);
955    /// let deserialized: Point = fory.deserialize_from(&mut reader).unwrap();
956    /// ```
957    pub fn deserialize_from<T: Serializer + ForyDefault>(
958        &self,
959        reader: &mut Reader,
960    ) -> Result<T, Error> {
961        self.with_read_context(|context| {
962            let outlive_buffer = unsafe { mem::transmute::<&[u8], &[u8]>(reader.bf) };
963            let mut new_reader = Reader::new(outlive_buffer);
964            new_reader.set_cursor(reader.cursor);
965            context.attach_reader(new_reader);
966            let result = self.deserialize_with_context(context);
967            let end = context.detach_reader().get_cursor();
968            reader.set_cursor(end);
969            result
970        })
971    }
972
973    /// Executes a closure with mutable access to a ReadContext for this Fory instance.
974    /// The context is stored in thread-local storage, eliminating all lock contention.
975    /// Uses fast path caching for O(1) access when using the same Fory instance repeatedly.
976    #[inline(always)]
977    fn with_read_context<R>(
978        &self,
979        f: impl FnOnce(&mut ReadContext) -> Result<R, Error>,
980    ) -> Result<R, Error> {
981        // SAFETY: Thread-local storage is only accessed from the current thread.
982        // We use UnsafeCell to avoid RefCell's runtime borrow checking overhead.
983        // The closure `f` does not recursively call with_read_context, so there's no aliasing.
984        READ_CONTEXTS.with(|cache| {
985            let cache = unsafe { &mut *cache.get() };
986            let id = self.id;
987            let config = self.config.clone();
988
989            let context = cache.get_or_insert_result(id, || {
990                // Only fetch type resolver when creating a new context
991                let type_resolver = self.get_final_type_resolver()?;
992                Ok(Box::new(ReadContext::new(type_resolver.clone(), config)))
993            })?;
994            f(context)
995        })
996    }
997
998    #[inline(always)]
999    fn deserialize_with_context<T: Serializer + ForyDefault>(
1000        &self,
1001        context: &mut ReadContext,
1002    ) -> Result<T, Error> {
1003        let result = self.deserialize_with_context_inner::<T>(context);
1004        context.reset();
1005        result
1006    }
1007
1008    #[inline(always)]
1009    fn deserialize_with_context_inner<T: Serializer + ForyDefault>(
1010        &self,
1011        context: &mut ReadContext,
1012    ) -> Result<T, Error> {
1013        let is_none = self.read_head(&mut context.reader)?;
1014        if is_none {
1015            return Ok(T::fory_default());
1016        }
1017        // Use RefMode based on config:
1018        // - If track_ref is enabled, use RefMode::Tracking for the root object
1019        // - Otherwise, use RefMode::NullOnly
1020        let ref_mode = if self.config.track_ref {
1021            RefMode::Tracking
1022        } else {
1023            RefMode::NullOnly
1024        };
1025        // TypeMeta is read inline during deserialization (streaming protocol)
1026        let result = <T as Serializer>::fory_read(context, ref_mode, true);
1027        context.ref_reader.resolve_callbacks();
1028        result
1029    }
1030
1031    #[inline(always)]
1032    fn read_head(&self, reader: &mut Reader) -> Result<bool, Error> {
1033        let bitmap = reader.read_u8()?;
1034        let peer_is_xlang = (bitmap & IS_CROSS_LANGUAGE_FLAG) != 0;
1035        ensure!(
1036            self.config.xlang == peer_is_xlang,
1037            Error::invalid_data("header bitmap mismatch at xlang bit")
1038        );
1039        let is_none = (bitmap & IS_NULL_FLAG) != 0;
1040        if is_none {
1041            return Ok(true);
1042        }
1043        Ok(false)
1044    }
1045}