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