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}