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