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}