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