fory_core/serializer/core.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::context::{ReadContext, WriteContext};
19use crate::error::Error;
20use crate::meta::FieldInfo;
21use crate::resolver::{RefFlag, RefMode, TypeInfo, TypeResolver};
22use crate::serializer::{bool, struct_};
23use crate::type_id::TypeId;
24use std::any::Any;
25use std::rc::Rc;
26
27/// Trait for creating default values during Fory deserialization.
28///
29/// `ForyDefault` is similar to Rust's standard `Default` trait but specifically designed
30/// for Fory's serialization framework. It provides a way to create "null" or default
31/// values when deserializing optional or nullable types.
32///
33/// # Why not use `Default`?
34///
35/// We can't add a blanket implementation `impl<T: Default> ForyDefault for T` because
36/// it would conflict with potential future implementations in upstream crates. For example,
37/// the standard library might add `impl Default for Rc<dyn Any>` in the future, which would
38/// cause a trait coherence conflict.
39///
40/// # When to implement
41///
42/// You should implement `ForyDefault` when:
43/// - Creating custom types that can be serialized with Fory
44/// - Your type needs to support nullable/optional representations
45/// - You want to define what the "null" or "default" value means for deserialization
46///
47/// # Examples
48///
49/// ```
50/// use fory_core::ForyDefault;
51///
52/// #[derive(Debug, PartialEq)]
53/// struct Point {
54/// x: i32,
55/// y: i32,
56/// }
57///
58/// impl ForyDefault for Point {
59/// fn fory_default() -> Self {
60/// Point { x: 0, y: 0 }
61/// }
62/// }
63///
64/// let default_point = Point::fory_default();
65/// assert_eq!(default_point, Point { x: 0, y: 0 });
66/// ```
67///
68/// For types that already implement `Default`, you can simply delegate:
69///
70/// ```
71/// use fory_core::ForyDefault;
72///
73/// #[derive(Default)]
74/// struct Config {
75/// timeout: u32,
76/// retries: u32,
77/// }
78///
79/// impl ForyDefault for Config {
80/// fn fory_default() -> Self {
81/// Default::default()
82/// }
83/// }
84/// ```
85pub trait ForyDefault: Sized {
86 /// Creates a default value for this type.
87 ///
88 /// This is used by Fory when deserializing null values or when a default
89 /// instance is needed during the deserialization process.
90 fn fory_default() -> Self;
91}
92
93// We can't add blanket impl for all T: Default because it conflicts with other impls.
94// For example, upstream crates may add a new impl of trait `std::default::Default` for
95// type `std::rc::Rc<(dyn std::any::Any + 'static)>` in future versions.
96// impl<T: Default + Sized> ForyDefault for T {
97// fn fory_default() -> Self {
98// Default::default()
99// }
100// }
101
102/// Core trait for Fory serialization and deserialization.
103///
104/// `Serializer` is the primary trait that enables types to be serialized and deserialized
105/// using Fory's high-performance cross-language protocol. All types that can be serialized
106/// with Fory must implement this trait, either manually or via the `#[derive(ForyStruct)]` macro.
107///
108/// # Architecture Overview
109///
110/// Fory's serialization consists of three main phases:
111///
112/// 1. **Reference tracking** (optional): Writes/reads null/not-null/ref flags for handling
113/// shared references and circular references
114/// 2. **Type information** (optional): Writes/reads type metadata for polymorphic types
115/// 3. **Data serialization**: Writes/reads the actual data payload
116///
117/// # Method Categories
118///
119/// ## Methods Users Must Implement (for custom serialization logic)
120///
121/// - [`fory_write_data`]: Core method to serialize your type's data
122/// - [`fory_read_data`]: Core method to deserialize your type's data
123/// - [`fory_type_id_dyn`]: Return runtime type ID for the instance
124/// - [`as_any`]: Downcast support for dynamic dispatch
125///
126/// ## Methods Implemented by Fory (override only if needed)
127///
128/// Most methods have default implementations suitable for common types:
129///
130/// - [`fory_write`]: Entry point for serialization (handles ref/type info)
131/// - [`fory_read`]: Entry point for deserialization (handles ref/type info)
132/// - [`fory_write_type_info`]: Write type metadata
133/// - [`fory_read_type_info`]: Read type metadata
134/// - [`fory_write_data_generic`]: Write data with generics support (for collections)
135/// - [`fory_read_with_type_info`]: Deserialize with pre-read type info
136///
137/// ## Type Query Methods
138///
139/// These provide compile-time and runtime type information:
140///
141/// - [`fory_static_type_id`]: Static type ID (defaults to TypeId::EXT for user types)
142/// - [`fory_get_type_id`]: Get registered type ID from TypeResolver
143/// - [`fory_concrete_type_id`]: Get Rust's std::any::TypeId
144/// - [`fory_is_option`]: Check if type is `Option<T>`
145/// - [`fory_is_none`]: Check if instance is None (for Option types)
146/// - [`fory_is_polymorphic`]: Check if type supports polymorphism
147/// - [`fory_is_shared_ref`]: Check if type is Rc/Arc
148/// - [`fory_reserved_space`]: Hint for buffer pre-allocation
149///
150/// # Typical Usage Pattern
151///
152/// For types that need custom serialization logic (EXT types), you only need to implement four methods:
153///
154/// ```rust,ignore
155/// impl Serializer for MyType {
156/// fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
157/// // Write your type's fields
158/// }
159///
160/// fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
161/// // Read your type's fields
162/// }
163///
164/// fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<fory_core::TypeId, Error> {
165/// Self::fory_get_type_id(type_resolver)
166/// }
167///
168/// fn as_any(&self) -> &dyn Any {
169/// self
170/// }
171/// }
172/// ```
173///
174/// # Derive Macro
175///
176/// For struct types, you can use the `#[derive(ForyStruct)]` macro instead of implementing manually:
177///
178/// ```rust,ignore
179/// #[derive(ForyStruct)]
180/// struct Point {
181/// x: f64,
182/// y: f64,
183/// }
184/// ```
185///
186/// # See Also
187///
188/// - [`ForyDefault`]: Trait for creating default values during deserialization
189/// - [`StructSerializer`]: Extended trait for struct-specific serialization
190///
191/// [`fory_write_data`]: Serializer::fory_write_data
192/// [`fory_read_data`]: Serializer::fory_read_data
193/// [`fory_write`]: Serializer::fory_write
194/// [`fory_read`]: Serializer::fory_read
195/// [`fory_write_type_info`]: Serializer::fory_write_type_info
196/// [`fory_read_type_info`]: Serializer::fory_read_type_info
197/// [`fory_write_data_generic`]: Serializer::fory_write_data_generic
198/// [`fory_read_with_type_info`]: Serializer::fory_read_with_type_info
199/// [`fory_type_id_dyn`]: Serializer::fory_type_id_dyn
200/// [`as_any`]: Serializer::as_any
201/// [`fory_static_type_id`]: Serializer::fory_static_type_id
202/// [`fory_get_type_id`]: Serializer::fory_get_type_id
203/// [`fory_concrete_type_id`]: Serializer::fory_concrete_type_id
204/// [`fory_is_option`]: Serializer::fory_is_option
205/// [`fory_is_none`]: Serializer::fory_is_none
206/// [`fory_is_polymorphic`]: Serializer::fory_is_polymorphic
207/// [`fory_is_shared_ref`]: Serializer::fory_is_shared_ref
208/// [`fory_reserved_space`]: Serializer::fory_reserved_space
209pub trait Serializer: 'static {
210 /// Entry point for serialization.
211 ///
212 /// This method orchestrates the complete serialization process, handling reference tracking,
213 /// type information, and delegating to [`fory_write_data`] for the actual data serialization.
214 ///
215 /// # Parameters
216 ///
217 /// * `ref_mode` - Controls how reference flags are written:
218 /// - `RefMode::None`: Skip writing ref flag entirely
219 /// - `RefMode::NullOnly`: Write `NotNullValue` flag (null check only)
220 /// - `RefMode::Tracking`: Write ref tracking flags (for Rc/Arc/Weak)
221 /// * `write_type_info` - When `true`, WRITES type information. When `false`, SKIPS writing type info.
222 /// * `has_generics` - Indicates if the type has generic parameters (used for collection meta).
223 ///
224 /// # Default Implementation (Fast Path)
225 ///
226 /// The default implementation uses a fast path suitable for primitives, strings, and time types:
227 ///
228 /// 1. If `ref_mode != RefMode::None`, writes `RefFlag::NotNullValue`
229 /// 2. If `write_type_info` is true, calls [`fory_write_type_info`]
230 /// 3. Calls [`fory_write_data_generic`] to write the actual data
231 ///
232 /// # When to Override
233 ///
234 /// You should override this method for:
235 ///
236 /// - **Option types**: Need to handle `None` with `RefFlag::Null`
237 /// - **Reference types** (Rc/Arc/Weak): Need full ref tracking with `RefWriter`
238 /// - **Polymorphic types**: Need to write actual runtime type instead of static type
239 ///
240 /// For regular types (structs, primitives, collections), the default implementation is sufficient.
241 ///
242 /// [`fory_write_data`]: Serializer::fory_write_data
243 /// [`fory_write_type_info`]: Serializer::fory_write_type_info
244 /// [`fory_write_data_generic`]: Serializer::fory_write_data_generic
245 #[inline(always)]
246 fn fory_write(
247 &self,
248 context: &mut WriteContext,
249 ref_mode: RefMode,
250 write_type_info: bool,
251 has_generics: bool,
252 ) -> Result<(), Error>
253 where
254 Self: Sized,
255 {
256 // Fast path: single comparison for primitives/strings/time types
257 if ref_mode != RefMode::None {
258 context.writer.write_i8(RefFlag::NotNullValue as i8);
259 }
260 if write_type_info {
261 Self::fory_write_type_info(context)?;
262 }
263 self.fory_write_data_generic(context, has_generics)
264 }
265
266 /// Write data with generic type parameter support.
267 ///
268 /// This method is primarily used by collection types (Vec, HashMap, etc.) that need to
269 /// write generic type information for their elements. For most types, this simply
270 /// delegates to [`fory_write_data`].
271 ///
272 /// # Parameters
273 ///
274 /// * `context` - Write context containing the buffer and type resolver
275 /// * `has_generics` - Indicates if the type has generic parameters that need metadata
276 ///
277 /// # Default Implementation
278 ///
279 /// The default implementation ignores `has_generics` and forwards to [`fory_write_data`]:
280 ///
281 /// ```rust,ignore
282 /// fn fory_write_data_generic(&self, context: &mut WriteContext, has_generics: bool) -> Result<(), Error> {
283 /// self.fory_write_data(context)
284 /// }
285 /// ```
286 ///
287 /// # When to Override
288 ///
289 /// Override this method for:
290 ///
291 /// - **Collection types** (Vec, HashMap, HashSet, etc.): Need to write element/key/value type metadata
292 /// - **Generic containers**: Any type that contains type parameters requiring runtime metadata
293 ///
294 /// For non-generic types (primitives, simple structs), use the default implementation.
295 ///
296 /// # Implementation Notes
297 ///
298 /// - Implemented by Fory for all collection types
299 /// - User types with custom serialization for non-generic types don't need to override
300 /// - Focus on implementing [`fory_write_data`] for custom types
301 ///
302 /// [`fory_write_data`]: Serializer::fory_write_data
303 #[inline(always)]
304 #[allow(unused_variables)]
305 fn fory_write_data_generic(
306 &self,
307 context: &mut WriteContext,
308 has_generics: bool,
309 ) -> Result<(), Error> {
310 self.fory_write_data(context)
311 }
312
313 /// **[USER IMPLEMENTATION REQUIRED]** Serialize the type's data to the buffer.
314 ///
315 /// This is the core serialization method that you must implement for custom types.
316 /// It should write all the type's fields and data to the buffer using the provided context.
317 ///
318 /// # Parameters
319 ///
320 /// * `context` - Write context providing:
321 /// - `context.writer`: Buffer to write binary data
322 /// - `context.type_resolver`: Registry of type information
323 /// - `context.ref_resolver`: Resolver for shared/circular references (if enabled)
324 ///
325 /// # Writing Data
326 ///
327 /// Use methods on `context.writer` to write primitive types:
328 ///
329 /// - `write_i8()`, `write_i16()`, `write_i32()`, `write_i64()`: Signed integers
330 /// - `write_u8()`, `write_u16()`, `write_u32()`, `write_u64()`: Unsigned integers
331 /// - `write_f32()`, `write_f64()`: Floating point numbers
332 /// - `write_bool()`: Boolean values
333 /// - `write_bytes()`: Raw byte arrays
334 ///
335 /// For nested types that implement `Serializer`, call their serialization:
336 ///
337 /// ```rust,ignore
338 /// // For types that implement Serializer
339 /// self.nested_field.fory_write(context, false, false, false)?;
340 /// ```
341 ///
342 /// # Examples
343 ///
344 /// ## Simple struct with primitive fields
345 ///
346 /// ```rust
347 /// use fory_core::{Serializer, ForyDefault};
348 /// use fory_core::WriteContext;
349 /// use fory_core::error::Error;
350 /// use std::any::Any;
351 ///
352 /// struct Point {
353 /// x: f64,
354 /// y: f64,
355 /// }
356 ///
357 /// impl ForyDefault for Point {
358 /// fn fory_default() -> Self {
359 /// Point { x: 0.0, y: 0.0 }
360 /// }
361 /// }
362 ///
363 /// impl Serializer for Point {
364 /// fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
365 /// // Write each field in order
366 /// context.writer.write_f64(self.x);
367 /// context.writer.write_f64(self.y);
368 /// Ok(())
369 /// }
370 ///
371 /// fn fory_read_data(context: &mut fory_core::ReadContext) -> Result<Self, Error>
372 /// where
373 /// Self: Sized + fory_core::ForyDefault,
374 /// {
375 /// let x = context.reader.read_f64()?;
376 /// let y = context.reader.read_f64()?;
377 /// Ok(Point { x, y })
378 /// }
379 ///
380 /// fn fory_type_id_dyn(&self, type_resolver: &fory_core::resolver::TypeResolver) -> Result<fory_core::TypeId, Error> {
381 /// Self::fory_get_type_id(type_resolver)
382 /// }
383 ///
384 /// fn as_any(&self) -> &dyn Any {
385 /// self
386 /// }
387 /// }
388 /// ```
389 ///
390 /// ## Struct with nested serializable types
391 ///
392 /// ```rust
393 /// use fory_core::{Serializer, ForyDefault, RefMode};
394 /// use fory_core::WriteContext;
395 /// use fory_core::error::Error;
396 /// use std::any::Any;
397 ///
398 /// struct Person {
399 /// name: String,
400 /// age: u32,
401 /// scores: Vec<i32>,
402 /// }
403 ///
404 /// impl ForyDefault for Person {
405 /// fn fory_default() -> Self {
406 /// Person {
407 /// name: String::new(),
408 /// age: 0,
409 /// scores: Vec::new(),
410 /// }
411 /// }
412 /// }
413 ///
414 /// impl Serializer for Person {
415 /// fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
416 /// // Write nested types using their Serializer implementations
417 /// self.name.fory_write(context, RefMode::None, false, false)?;
418 /// context.writer.write_u32(self.age);
419 /// self.scores.fory_write(context, RefMode::None, false, true)?; // has_generics=true for Vec
420 /// Ok(())
421 /// }
422 ///
423 /// fn fory_read_data(context: &mut fory_core::ReadContext) -> Result<Self, Error>
424 /// where
425 /// Self: Sized + fory_core::ForyDefault,
426 /// {
427 /// let name = String::fory_read(context, RefMode::None, false)?;
428 /// let age = context.reader.read_u32()?;
429 /// let scores = Vec::<i32>::fory_read(context, RefMode::None, false)?;
430 /// Ok(Person { name, age, scores })
431 /// }
432 ///
433 /// fn fory_type_id_dyn(&self, type_resolver: &fory_core::resolver::TypeResolver) -> Result<fory_core::TypeId, Error> {
434 /// Self::fory_get_type_id(type_resolver)
435 /// }
436 ///
437 /// fn as_any(&self) -> &dyn Any {
438 /// self
439 /// }
440 /// }
441 /// ```
442 ///
443 /// # Implementation Guidelines
444 ///
445 /// 1. **Field order matters**: Write fields in a consistent order; read them in the same order
446 /// 2. **No metadata here**: Don't write type info or ref flags; that's handled by [`fory_write`]
447 /// 3. **Use Serializer for nested types**: Leverage existing implementations for standard types
448 /// 4. **Error handling**: Propagate errors with `?`; don't swallow them
449 /// 5. **Performance**: Minimize allocations; write directly to the buffer
450 ///
451 /// # Common Patterns
452 ///
453 /// ```rust,ignore
454 /// // Writing primitives directly
455 /// context.writer.write_i32(self.count);
456 ///
457 /// // Writing nested Serializer types
458 /// self.nested.fory_write(context, false, false, false)?;
459 ///
460 /// // Writing collections with generics
461 /// self.items.fory_write(context, false, false, true)?;
462 ///
463 /// // Writing optional types
464 /// self.optional.fory_write(context, true, false, false)?; // write_ref_info=true
465 /// ```
466 ///
467 /// # See Also
468 ///
469 /// - [`fory_read_data`]: Corresponding deserialization method
470 /// - [`fory_write`]: High-level serialization entry point
471 /// - [`WriteContext`]: Context providing buffer and resolver access
472 ///
473 /// [`fory_write`]: Serializer::fory_write
474 /// [`fory_read_data`]: Serializer::fory_read_data
475 fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error>;
476
477 /// Write type metadata to the buffer.
478 ///
479 /// This method writes type information that allows Fory to identify and deserialize
480 /// the type correctly, especially for polymorphic scenarios.
481 ///
482 /// # Default Implementation
483 ///
484 /// The default implementation writes:
485 ///
486 /// 1. Static type ID from [`fory_static_type_id`]
487 /// 2. Rust's `std::any::TypeId` for runtime type identification
488 ///
489 /// ```rust,ignore
490 /// fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
491 /// let rs_type_id = std::any::TypeId::of::<Self>();
492 /// context.write_any_type_info(Self::fory_static_type_id() as u32, rs_type_id)?;
493 /// Ok(())
494 /// }
495 /// ```
496 ///
497 /// # When to Override
498 ///
499 /// Override this method for:
500 ///
501 /// - **Built-in types**: Fory's internal types override for optimized performance
502 /// - **Custom type ID schemes**: If you need special type identification logic
503 ///
504 /// For user types with custom serialization, the default implementation is typically sufficient.
505 ///
506 /// # Implementation Notes
507 ///
508 /// - Called by [`fory_write`] when `write_type_info` is true
509 /// - Implemented by Fory for all built-in types with optimized paths
510 /// - User types with custom serialization rarely need to override this
511 ///
512 /// [`fory_static_type_id`]: Serializer::fory_static_type_id
513 /// [`fory_write`]: Serializer::fory_write
514 #[inline(always)]
515 fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error>
516 where
517 Self: Sized,
518 {
519 // Serializer for internal types should overwrite this method for faster performance.
520 let rs_type_id = std::any::TypeId::of::<Self>();
521 context.write_any_type_info(Self::fory_static_type_id() as u32, rs_type_id)?;
522 Ok(())
523 }
524
525 /// Entry point for deserialization.
526 ///
527 /// This method orchestrates the complete deserialization process, handling reference tracking,
528 /// type information validation, and delegating to [`fory_read_data`] for the actual data deserialization.
529 ///
530 /// # Parameters
531 ///
532 /// * `ref_mode` - Controls how reference flags are read:
533 /// - `RefMode::None`: Skip reading ref flag entirely
534 /// - `RefMode::NullOnly`: Read flag, return default on null
535 /// - `RefMode::Tracking`: Full ref tracking (for Rc/Arc/Weak)
536 /// * `read_type_info` - When `true`, READS type information from buffer. When `false`, SKIPS reading type info.
537 ///
538 /// # Type Requirements
539 ///
540 /// This method requires `Self: Sized + ForyDefault` because:
541 ///
542 /// - **Sized**: Need to construct concrete instances
543 /// - **ForyDefault**: Need to create default/null values for optional types
544 ///
545 /// # Default Implementation (Fast Path)
546 ///
547 /// The default implementation uses a fast path suitable for primitives, strings, and time types:
548 ///
549 /// 1. If `ref_mode != RefMode::None`:
550 /// - Reads ref flag from buffer
551 /// - Returns `ForyDefault::fory_default()` for null values
552 /// 2. If `read_type_info` is true, calls [`fory_read_type_info`]
553 /// 3. Calls [`fory_read_data`] to read the actual data
554 ///
555 /// # When to Override
556 ///
557 /// Override this method for:
558 ///
559 /// - **Option types**: Need custom null handling logic
560 /// - **Reference types** (Rc/Arc/Weak): Need custom ref tracking with RefReader
561 /// - **Polymorphic types**: Need to dispatch based on actual runtime type
562 ///
563 /// For regular types (structs, primitives, collections), the default implementation is sufficient.
564 ///
565 /// [`fory_read_data`]: Serializer::fory_read_data
566 /// [`fory_read_type_info`]: Serializer::fory_read_type_info
567 /// [`fory_write`]: Serializer::fory_write
568 #[inline(always)]
569 fn fory_read(
570 context: &mut ReadContext,
571 ref_mode: RefMode,
572 read_type_info: bool,
573 ) -> Result<Self, Error>
574 where
575 Self: Sized + ForyDefault,
576 {
577 // Fast path: single comparison for primitives/strings/time types
578 if ref_mode != RefMode::None {
579 let ref_flag = context.reader.read_i8()?;
580 if ref_flag == RefFlag::Null as i8 {
581 return Ok(Self::fory_default());
582 }
583 // NotNullValue or RefValue both mean "continue reading" for non-trackable types
584 }
585 if read_type_info {
586 Self::fory_read_type_info(context)?;
587 }
588 Self::fory_read_data(context)
589 }
590
591 /// Deserialize with pre-read type information.
592 ///
593 /// This method is used when type information has already been read from the buffer
594 /// and needs to be passed to the deserialization logic. This is common in polymorphic
595 /// deserialization scenarios where the runtime type differs from the static type.
596 ///
597 /// # Parameters
598 ///
599 /// * `ref_mode` - Controls how reference flags are read (see [`fory_read`])
600 /// * `type_info` - Type information that has already been read ahead. DO NOT read type info again from buffer.
601 ///
602 /// # Important
603 ///
604 /// **DO NOT** read type info from the buffer in this method. The `type_info` parameter
605 /// contains the already-read type metadata. Reading it again will cause buffer position errors.
606 ///
607 /// # Default Implementation
608 ///
609 /// The default implementation ignores the provided `type_info` and delegates to [`fory_read`]:
610 ///
611 /// ```rust,ignore
612 /// fn fory_read_with_type_info(
613 /// context: &mut ReadContext,
614 /// ref_mode: RefMode,
615 /// type_info: Rc<TypeInfo>,
616 /// ) -> Result<Self, Error> {
617 /// // Ignore type_info since static type matches
618 /// Self::fory_read(context, ref_mode, false) // read_type_info=false
619 /// }
620 /// ```
621 ///
622 /// This works for:
623 ///
624 /// - **Monomorphic types**: Static type matches runtime type
625 /// - **Final types**: Types that don't participate in polymorphism
626 /// - **User-defined types**: Types registered with Fory that don't require polymorphism
627 ///
628 /// # When to Override
629 ///
630 /// Override this method for:
631 ///
632 /// - **Trait objects** (dyn Trait): Need to dispatch to concrete implementation based on type_info
633 /// - **Reference types with polymorphic targets**: Rc\<dyn Trait\>, Arc\<dyn Trait\>
634 /// - **Custom polymorphic types**: Types with runtime type variation
635 ///
636 /// [`fory_read`]: Serializer::fory_read
637 #[inline(always)]
638 #[allow(unused_variables)]
639 fn fory_read_with_type_info(
640 context: &mut ReadContext,
641 ref_mode: RefMode,
642 type_info: Rc<TypeInfo>,
643 ) -> Result<Self, Error>
644 where
645 Self: Sized + ForyDefault,
646 {
647 // Default implementation ignores the provided typeinfo because the static type matches.
648 Self::fory_read(context, ref_mode, false)
649 }
650
651 /// **[USER IMPLEMENTATION REQUIRED]** Deserialize the type's data from the buffer.
652 ///
653 /// This is the core deserialization method that you must implement for custom types.
654 /// It should read all the type's fields and data from the buffer in the same order
655 /// they were written by [`fory_write_data`].
656 ///
657 /// # Parameters
658 ///
659 /// * `context` - Read context providing:
660 /// - `context.reader`: Buffer to read binary data
661 /// - `context.type_resolver`: Registry of type information
662 /// - `context.ref_resolver`: Resolver for shared/circular references (if enabled)
663 ///
664 /// # Type Requirements
665 ///
666 /// Requires `Self: Sized + ForyDefault`:
667 ///
668 /// - **Sized**: Need to construct concrete instances on the stack
669 /// - **ForyDefault**: Need to create default/null values for optional fields
670 ///
671 /// # Reading Data
672 ///
673 /// Use methods on `context.reader` to read primitive types:
674 ///
675 /// - `read_i8()`, `read_i16()`, `read_i32()`, `read_i64()`: Signed integers
676 /// - `read_u8()`, `read_u16()`, `read_u32()`, `read_u64()`: Unsigned integers
677 /// - `read_f32()`, `read_f64()`: Floating point numbers
678 /// - `read_bool()`: Boolean values
679 /// - `read_bytes()`: Raw byte arrays
680 ///
681 /// For nested types that implement `Serializer`, call their deserialization:
682 ///
683 /// ```rust,ignore
684 /// // For types that implement Serializer
685 /// let field = T::fory_read(context, false, false)?;
686 /// ```
687 ///
688 /// # Examples
689 ///
690 /// ## Simple struct with primitive fields
691 ///
692 /// ```rust
693 /// use fory_core::{Serializer, ForyDefault};
694 /// use fory_core::{ReadContext, WriteContext};
695 /// use fory_core::error::Error;
696 /// use std::any::Any;
697 ///
698 /// #[derive(Debug, PartialEq)]
699 /// struct Point {
700 /// x: f64,
701 /// y: f64,
702 /// }
703 ///
704 /// impl ForyDefault for Point {
705 /// fn fory_default() -> Self {
706 /// Point { x: 0.0, y: 0.0 }
707 /// }
708 /// }
709 ///
710 /// impl Serializer for Point {
711 /// fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
712 /// context.writer.write_f64(self.x);
713 /// context.writer.write_f64(self.y);
714 /// Ok(())
715 /// }
716 ///
717 /// fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error>
718 /// where
719 /// Self: Sized + ForyDefault,
720 /// {
721 /// // Read fields in the same order as written
722 /// let x = context.reader.read_f64()?;
723 /// let y = context.reader.read_f64()?;
724 /// Ok(Point { x, y })
725 /// }
726 ///
727 /// fn fory_type_id_dyn(&self, type_resolver: &fory_core::resolver::TypeResolver) -> Result<fory_core::TypeId, Error> {
728 /// Self::fory_get_type_id(type_resolver)
729 /// }
730 ///
731 /// fn as_any(&self) -> &dyn Any {
732 /// self
733 /// }
734 /// }
735 /// ```
736 ///
737 /// ## Struct with nested serializable types
738 ///
739 /// ```rust
740 /// use fory_core::{Serializer, ForyDefault, RefMode};
741 /// use fory_core::{ReadContext, WriteContext};
742 /// use fory_core::error::Error;
743 /// use std::any::Any;
744 ///
745 /// #[derive(Debug, PartialEq)]
746 /// struct Person {
747 /// name: String,
748 /// age: u32,
749 /// scores: Vec<i32>,
750 /// }
751 ///
752 /// impl ForyDefault for Person {
753 /// fn fory_default() -> Self {
754 /// Person {
755 /// name: String::new(),
756 /// age: 0,
757 /// scores: Vec::new(),
758 /// }
759 /// }
760 /// }
761 ///
762 /// impl Serializer for Person {
763 /// fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
764 /// self.name.fory_write(context, RefMode::None, false, false)?;
765 /// context.writer.write_u32(self.age);
766 /// self.scores.fory_write(context, RefMode::None, false, true)?;
767 /// Ok(())
768 /// }
769 ///
770 /// fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error>
771 /// where
772 /// Self: Sized + ForyDefault,
773 /// {
774 /// // Read nested types in the same order as written
775 /// let name = String::fory_read(context, RefMode::None, false)?;
776 /// let age = context.reader.read_u32()?;
777 /// let scores = Vec::<i32>::fory_read(context, RefMode::None, false)?;
778 /// Ok(Person { name, age, scores })
779 /// }
780 ///
781 /// fn fory_type_id_dyn(&self, type_resolver: &fory_core::resolver::TypeResolver) -> Result<fory_core::TypeId, Error> {
782 /// Self::fory_get_type_id(type_resolver)
783 /// }
784 ///
785 /// fn as_any(&self) -> &dyn Any {
786 /// self
787 /// }
788 /// }
789 /// ```
790 ///
791 /// ## Struct with optional fields
792 ///
793 /// ```rust,ignore
794 /// use fory_core::{Serializer, ForyDefault};
795 /// use fory_core::{ReadContext, WriteContext};
796 /// use fory_core::error::Error;
797 /// use std::any::Any;
798 ///
799 /// #[derive(Debug, PartialEq)]
800 /// struct Config {
801 /// name: String,
802 /// timeout: Option<u32>,
803 /// }
804 ///
805 /// impl ForyDefault for Config {
806 /// fn fory_default() -> Self {
807 /// Config {
808 /// name: String::new(),
809 /// timeout: None,
810 /// }
811 /// }
812 /// }
813 ///
814 /// impl Serializer for Config {
815 /// fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
816 /// self.name.fory_write(context, false, false, false)?;
817 /// // Option needs ref tracking to handle None
818 /// self.timeout.fory_write(context, true, false, false)?;
819 /// Ok(())
820 /// }
821 ///
822 /// fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error>
823 /// where
824 /// Self: Sized + ForyDefault,
825 /// {
826 /// let name = String::fory_read(context, false, false)?;
827 /// // Read Option with ref tracking enabled
828 /// let timeout = Option::<u32>::fory_read(context, true, false)?;
829 /// Ok(Config { name, timeout })
830 /// }
831 ///
832 /// fn fory_type_id_dyn(&self, type_resolver: &fory_core::resolver::TypeResolver) -> Result<fory_core::TypeId, Error> {
833 /// Self::fory_get_type_id(type_resolver)
834 /// }
835 ///
836 /// fn as_any(&self) -> &dyn Any {
837 /// self
838 /// }
839 /// }
840 /// ```
841 ///
842 /// # Implementation Guidelines
843 ///
844 /// 1. **Mirror write order**: Read fields in the exact same order as [`fory_write_data`] writes them
845 /// 2. **Error propagation**: Use `?` operator to propagate read errors
846 /// 3. **No metadata reading**: Don't read ref flags or type info; that's handled by [`fory_read`]
847 /// 4. **Use Serializer for nested types**: Leverage existing implementations
848 /// 5. **Handle errors gracefully**: Return descriptive errors for invalid data
849 ///
850 /// # Common Patterns
851 ///
852 /// ```rust,ignore
853 /// // Reading primitives
854 /// let count = context.reader.read_i32()?;
855 ///
856 /// // Reading nested Serializer types
857 /// let nested = T::fory_read(context, false, false)?;
858 ///
859 /// // Reading collections
860 /// let items = Vec::<T>::fory_read(context, false, false)?;
861 ///
862 /// // Reading optional types
863 /// let optional = Option::<T>::fory_read(context, true, false)?;
864 /// ```
865 ///
866 /// # Error Handling
867 ///
868 /// Return errors for:
869 ///
870 /// - **Buffer underflow**: Not enough data to read
871 /// - **Invalid data**: Data doesn't match expected format
872 /// - **Version mismatch**: Incompatible serialization format
873 ///
874 /// ```rust,ignore
875 /// if value > MAX_ALLOWED {
876 /// return Err(Error::invalid_data(format!("Value {} exceeds maximum", value)));
877 /// }
878 /// ```
879 ///
880 /// # See Also
881 ///
882 /// - [`fory_write_data`]: Corresponding serialization method
883 /// - [`fory_read`]: High-level deserialization entry point
884 /// - [`ForyDefault`]: Trait for creating default values
885 /// - [`ReadContext`]: Context providing buffer and resolver access
886 ///
887 /// [`fory_write_data`]: Serializer::fory_write_data
888 /// [`fory_read`]: Serializer::fory_read
889 fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error>
890 where
891 Self: Sized + ForyDefault;
892
893 /// Read and validate type metadata from the buffer.
894 ///
895 /// This method reads type information to verify that the data in the buffer
896 /// matches the expected type. It's the counterpart to [`fory_write_type_info`].
897 ///
898 /// # Default Implementation
899 ///
900 /// The default implementation reads and validates the type info:
901 ///
902 /// ```rust,ignore
903 /// fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
904 /// context.read_any_type_info()?;
905 /// Ok(())
906 /// }
907 /// ```
908 ///
909 /// # When to Override
910 ///
911 /// Override this method for:
912 ///
913 /// - **Built-in types**: Fory's internal types override for optimized performance
914 /// - **Custom validation logic**: If you need special type checking
915 ///
916 /// For user types with custom serialization, the default implementation is typically sufficient.
917 ///
918 /// # Implementation Notes
919 ///
920 /// - Called by [`fory_read`] when `read_type_info` is true
921 /// - Implemented by Fory for all built-in types with optimized paths
922 /// - User types with custom serialization rarely need to override this
923 ///
924 /// [`fory_write_type_info`]: Serializer::fory_write_type_info
925 /// [`fory_read`]: Serializer::fory_read
926 #[inline(always)]
927 fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error>
928 where
929 Self: Sized,
930 {
931 // Serializer for internal types should overwrite this method for faster performance.
932 context.read_any_type_info()?;
933 Ok(())
934 }
935
936 /// Check if this type is `Option<T>`.
937 ///
938 /// # Returns
939 ///
940 /// - `true` if the type is `Option<T>`
941 /// - `false` for all other types (default)
942 ///
943 /// # Implementation Notes
944 ///
945 /// - Implemented by Fory for `Option<T>` to return `true`
946 /// - User types with custom serialization should not override this
947 /// - Used internally for null handling optimization
948 #[inline(always)]
949 fn fory_is_option() -> bool
950 where
951 Self: Sized,
952 {
953 false
954 }
955
956 /// Check if this instance represents a `None` value.
957 ///
958 /// This method is used for runtime checking of optional values.
959 ///
960 /// # Returns
961 ///
962 /// - `true` if the instance is `Option::None`
963 /// - `false` for all other values (default)
964 ///
965 /// # Implementation Notes
966 ///
967 /// - Implemented by Fory for `Option<T>` to check None state
968 /// - User types with custom serialization should not override this
969 /// - Used with [`fory_is_option`] for null handling
970 ///
971 /// [`fory_is_option`]: Serializer::fory_is_option
972 #[inline(always)]
973 fn fory_is_none(&self) -> bool {
974 false
975 }
976
977 /// Check if this type supports polymorphic serialization.
978 ///
979 /// Polymorphic types can have different runtime types than their static type,
980 /// requiring special handling during serialization and deserialization.
981 ///
982 /// # Returns
983 ///
984 /// - `true` if the type is polymorphic (trait objects, dynamic dispatch)
985 /// - `false` for monomorphic types (default)
986 ///
987 /// # Examples of Polymorphic Types
988 ///
989 /// - Trait objects: `Box<dyn Trait>`, `Rc<dyn Trait>`, `Arc<dyn Trait>`
990 ///
991 /// # Implementation Notes
992 ///
993 /// - Implemented by Fory for all polymorphic types
994 /// - User types with custom serialization typically should not override this
995 /// - Used to determine if type info must be written
996 #[inline(always)]
997 fn fory_is_polymorphic() -> bool
998 where
999 Self: Sized,
1000 {
1001 false
1002 }
1003
1004 /// Check if this type is a shared reference (Rc/Arc).
1005 ///
1006 /// Shared references require special handling for reference tracking
1007 /// to support proper sharing and circular reference detection.
1008 ///
1009 /// # Returns
1010 ///
1011 /// - `true` if the type is `Rc<T>` or `Arc<T>`
1012 /// - `false` for all other types (default)
1013 ///
1014 /// # Implementation Notes
1015 ///
1016 /// - Implemented by Fory for `Rc<T>` and `Arc<T>`
1017 /// - User types with custom serialization should not override this
1018 /// - Used for reference tracking and deduplication
1019 #[inline(always)]
1020 fn fory_is_shared_ref() -> bool
1021 where
1022 Self: Sized,
1023 {
1024 false
1025 }
1026
1027 #[inline(always)]
1028 fn fory_is_wrapper_type() -> bool
1029 where
1030 Self: Sized,
1031 {
1032 Self::fory_is_shared_ref()
1033 }
1034
1035 /// Get the static Fory type ID for this type.
1036 ///
1037 /// Type IDs are Fory's internal type identification system, separate from
1038 /// Rust's `std::any::TypeId`. They're used for cross-language serialization
1039 /// and protocol compatibility.
1040 ///
1041 /// # Returns
1042 ///
1043 /// - For built-in types: Specific type ID (e.g., `TypeId::I32`, `TypeId::STRING`)
1044 /// - For external types: `TypeId::EXT` (default)
1045 ///
1046 /// # Type ID Categories
1047 ///
1048 /// - **Primitives**: `BOOL`, `I8`, `I16`, `I32`, `I64`, `U8`, `U16`, `U32`, `U64`, `USIZE`, `U128`, `F32`, `F64`
1049 /// - **Strings**: `STRING`
1050 /// - **Collections**: `LIST`, `MAP`, `SET`
1051 /// - **Structs**: `STRUCT`
1052 /// - **Enums**: `ENUM`
1053 /// - **User types**: `EXT` for user types with custom serialization logic
1054 ///
1055 /// # Implementation Notes
1056 ///
1057 /// - Default returns `TypeId::EXT` for user types
1058 /// - Fory implements specific type IDs for all built-in types
1059 /// - User types with custom serialization should use the default
1060 /// - This is a compile-time constant
1061 #[inline(always)]
1062 fn fory_static_type_id() -> TypeId
1063 where
1064 Self: Sized,
1065 {
1066 // set to ext to simplify the user defined serializer.
1067 // serializer for other types will override this method.
1068 TypeId::EXT
1069 }
1070
1071 /// Get the registered type ID from the type resolver.
1072 ///
1073 /// This method looks up the type's assigned ID in the type registry,
1074 /// which is required for serialization of external types.
1075 ///
1076 /// # Parameters
1077 ///
1078 /// * `type_resolver` - The type registry to query
1079 ///
1080 /// # Returns
1081 ///
1082 /// The numeric type ID assigned to this type during registration.
1083 ///
1084 /// # Errors
1085 ///
1086 /// Returns an error if the type is not registered with the resolver.
1087 ///
1088 /// # Implementation Notes
1089 ///
1090 /// - Default implementation looks up via `std::any::TypeId`
1091 /// - User types must be registered before serialization
1092 /// - Built-in types have pre-assigned IDs
1093 /// - This is typically called by [`fory_type_id_dyn`]
1094 ///
1095 /// [`fory_type_id_dyn`]: Serializer::fory_type_id_dyn
1096 #[inline(always)]
1097 fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<TypeId, Error>
1098 where
1099 Self: Sized,
1100 {
1101 match type_resolver.get_type_info(&std::any::TypeId::of::<Self>()) {
1102 Ok(info) => Ok(info.get_type_id()),
1103 Err(e) => Err(Error::enhance_type_error::<Self>(e)),
1104 }
1105 }
1106
1107 #[inline(always)]
1108 fn fory_get_type_info(type_resolver: &TypeResolver) -> Result<Rc<TypeInfo>, Error>
1109 where
1110 Self: Sized,
1111 {
1112 match type_resolver.get_type_info(&std::any::TypeId::of::<Self>()) {
1113 Ok(info) => Ok(info),
1114 Err(e) => Err(Error::enhance_type_error::<Self>(e)),
1115 }
1116 }
1117
1118 /// **[USER IMPLEMENTATION REQUIRED]** Get the runtime type ID for this instance.
1119 ///
1120 /// This method returns the type ID for the actual runtime type of the instance,
1121 /// which may differ from the static type for polymorphic types.
1122 ///
1123 /// # Parameters
1124 ///
1125 /// * `type_resolver` - The type registry to query
1126 ///
1127 /// # Returns
1128 ///
1129 /// The numeric type ID for this instance's runtime type.
1130 ///
1131 /// # Implementation Pattern
1132 ///
1133 /// For most types, simply delegate to [`fory_get_type_id`]:
1134 ///
1135 /// ```rust,ignore
1136 /// fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<fory_core::TypeId, Error> {
1137 /// Self::fory_get_type_id(type_resolver)
1138 /// }
1139 /// ```
1140 ///
1141 /// For polymorphic types, return the actual runtime type:
1142 ///
1143 /// ```rust,ignore
1144 /// fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<fory_core::TypeId, Error> {
1145 /// // Get the actual type ID based on runtime type
1146 /// self.get_actual_type().fory_get_type_id(type_resolver)
1147 /// }
1148 /// ```
1149 ///
1150 /// [`fory_get_type_id`]: Serializer::fory_get_type_id
1151 fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error>;
1152
1153 /// Get Rust's `std::any::TypeId` for this instance.
1154 ///
1155 /// Returns the runtime type identifier from Rust's type system.
1156 /// This is used for type resolution and registration.
1157 ///
1158 /// # Returns
1159 ///
1160 /// The `std::any::TypeId` for this instance's concrete type.
1161 ///
1162 /// # Implementation Notes
1163 ///
1164 /// - Default implementation uses `TypeId::of::<Self>()`
1165 /// - User types with custom serialization should not override this
1166 /// - Used by type resolution infrastructure
1167 #[inline(always)]
1168 fn fory_concrete_type_id(&self) -> std::any::TypeId {
1169 std::any::TypeId::of::<Self>()
1170 }
1171
1172 /// Hint for buffer pre-allocation size.
1173 ///
1174 /// This method provides a size hint for how much buffer space to pre-allocate
1175 /// before serializing this type. Accurate hints improve performance by reducing
1176 /// buffer reallocations.
1177 ///
1178 /// # Returns
1179 ///
1180 /// - Estimated maximum size in bytes for this type
1181 /// - `0` if unknown or variable size (default)
1182 ///
1183 /// # Implementation Guidelines
1184 ///
1185 /// Return a conservative upper bound:
1186 ///
1187 /// ```rust,ignore
1188 /// fn fory_reserved_space() -> usize {
1189 /// std::mem::size_of::<Self>() + overhead
1190 /// }
1191 /// ```
1192 ///
1193 /// # Examples
1194 ///
1195 /// - Fixed-size struct: `std::mem::size_of::<Self>() + metadata_size`
1196 /// - Variable-size: Return `0` (collections, strings)
1197 ///
1198 /// # Implementation Notes
1199 ///
1200 /// - Default returns `0` (no pre-allocation)
1201 /// - Fory implements size hints for fixed-size types
1202 /// - User types with custom serialization can override for performance
1203 /// - Overestimation wastes memory; underestimation requires reallocation
1204 #[inline(always)]
1205 fn fory_reserved_space() -> usize
1206 where
1207 Self: Sized,
1208 {
1209 std::mem::size_of::<Self>()
1210 }
1211
1212 /// **[USER IMPLEMENTATION REQUIRED]** Downcast to `&dyn Any` for dynamic type checking.
1213 ///
1214 /// This method enables runtime type checking and downcasting, required for
1215 /// Fory's type system integration.
1216 ///
1217 /// # Returns
1218 ///
1219 /// A reference to this instance as `&dyn Any`.
1220 ///
1221 /// # Implementation Pattern
1222 ///
1223 /// Always implement this by returning `self`:
1224 ///
1225 /// ```rust,ignore
1226 /// fn as_any(&self) -> &dyn Any {
1227 /// self
1228 /// }
1229 /// ```
1230 ///
1231 /// # Implementation Notes
1232 ///
1233 /// - Required for all types implementing `Serializer`
1234 /// - Enables `downcast_ref::<T>()` on serialized values
1235 /// - Used by Fory's polymorphic deserialization
1236 fn as_any(&self) -> &dyn Any;
1237}
1238
1239/// Extended trait for struct and enum serialization.
1240///
1241/// `StructSerializer` extends [`Serializer`] with capabilities specific to struct and enum types,
1242/// including field metadata, schema evolution, and compatibility features. This trait is used
1243/// internally by Fory and automatically implemented by the derive macro.
1244///
1245/// # Important: Do NOT Implement This for Custom User Types
1246///
1247/// **User types with custom serialization should NOT implement this trait.** This trait is:
1248///
1249/// - **Only for derive-based types**: Automatically implemented by `#[derive(ForyStruct)]`
1250/// - **Internal infrastructure**: Used by Fory's struct/enum deserialization engine
1251/// - **Not for manual implementation**: Unless you're extending Fory's core functionality
1252///
1253/// For user types that need custom serialization logic (EXT types), implement only the [`Serializer`] trait.
1254///
1255/// # Purpose
1256///
1257/// This trait enables Fory's advanced struct/enum features:
1258///
1259/// - **Field introspection**: Access to struct field metadata for serialization
1260/// - **Schema evolution**: Forward and backward compatibility for struct/enum changes
1261/// - **Compatible deserialization**: Read structs with different field sets (added/removed fields)
1262/// - **Type indexing**: Efficient type lookup for struct/enum types
1263/// - **Hash-based identification**: Support for versioned struct schemas
1264///
1265/// # Automatic Implementation
1266///
1267/// The `#[derive(ForyStruct)]` macro automatically implements this trait for structs and enums:
1268///
1269/// ```rust,ignore
1270/// #[derive(ForyStruct)]
1271/// struct Point {
1272/// x: f64,
1273/// y: f64,
1274/// }
1275/// // StructSerializer is automatically implemented
1276/// // Users should never implement this manually for custom serialization
1277/// ```
1278///
1279/// # Usage by Fory
1280///
1281/// Fory uses this trait internally for:
1282///
1283/// - **Struct serialization**: Writing field metadata and data
1284/// - **Enum serialization**: Writing variant information
1285/// - **Compatible reads**: Handling schema evolution scenarios
1286/// - **Type registration**: Managing struct/enum type metadata
1287///
1288/// # Implementation Notes
1289///
1290/// - **Do not implement manually** for user types with custom serialization (EXT types)
1291/// - **Only via derive macro**: `#[derive(ForyStruct)]` is the only supported way
1292/// - **Internal use only**: Methods are called by Fory's serialization engine
1293/// - **Schema evolution**: Enables adding/removing fields without breaking compatibility
1294///
1295/// # See Also
1296///
1297/// - [`Serializer`]: Base trait that user types with custom serialization should implement
1298/// - [`FieldInfo`]: Metadata about struct fields
1299///
1300/// [`Serializer`]: Serializer
1301pub trait StructSerializer: Serializer + 'static {
1302 /// Get metadata about this struct's fields.
1303 ///
1304 /// Returns information about each field in the struct, including names,
1305 /// types, and offsets. This is used for schema evolution and compatibility.
1306 ///
1307 /// # Parameters
1308 ///
1309 /// * `type_resolver` - The type registry for looking up field types
1310 ///
1311 /// # Returns
1312 ///
1313 /// A vector of [`FieldInfo`] describing each field, or an empty vector by default.
1314 ///
1315 /// # Implementation Notes
1316 ///
1317 /// - Implemented automatically by `#[derive(ForyStruct)]` macro
1318 /// - Default returns empty vector (no fields)
1319 /// - **Do not implement** for user types with custom serialization (EXT types)
1320 #[allow(unused_variables)]
1321 fn fory_fields_info(type_resolver: &TypeResolver) -> Result<Vec<FieldInfo>, Error> {
1322 Ok(Vec::default())
1323 }
1324
1325 #[allow(unused_variables)]
1326 fn fory_variants_fields_info(
1327 type_resolver: &TypeResolver,
1328 ) -> Result<Vec<(String, std::any::TypeId, Vec<FieldInfo>)>, Error> {
1329 Ok(Vec::default())
1330 }
1331
1332 /// Get the type index for fast struct type lookup.
1333 ///
1334 /// Type index provides O(1) lookup for struct types in the type registry.
1335 ///
1336 /// # Returns
1337 ///
1338 /// A unique index assigned to this struct type.
1339 ///
1340 /// # Implementation Notes
1341 ///
1342 /// - Implemented automatically by `#[derive(ForyStruct)]` macro
1343 /// - Used for efficient type resolution
1344 /// - **Do not implement** for user types with custom serialization (EXT types)
1345 fn fory_type_index() -> u32 {
1346 unimplemented!()
1347 }
1348
1349 /// Get the actual type ID considering registration and compatibility modes.
1350 ///
1351 /// This method computes the effective type ID based on how the type was registered
1352 /// and whether compatibility mode is enabled.
1353 ///
1354 /// # Parameters
1355 ///
1356 /// * `type_id` - The base type ID
1357 /// * `register_by_name` - Whether type was registered by name (vs by hash)
1358 /// * `compatible` - Whether compatibility mode is enabled
1359 /// * `xlang` - Whether xlang mode is enabled
1360 ///
1361 /// # Returns
1362 ///
1363 /// The actual type ID to use for serialization/deserialization.
1364 ///
1365 /// # Implementation Notes
1366 ///
1367 /// - Default delegates to `struct_::actual_type_id`
1368 /// - Handles type ID transformations for compatibility
1369 /// - **Do not override** for user types with custom serialization (EXT types)
1370 #[inline(always)]
1371 fn fory_actual_type_id(
1372 type_id: u32,
1373 register_by_name: bool,
1374 compatible: bool,
1375 xlang: bool,
1376 ) -> u32 {
1377 let _ = xlang; // Default implementation ignores xlang parameter
1378 struct_::actual_type_id(type_id, register_by_name, compatible)
1379 }
1380
1381 /// Get sorted field names for consistent serialization order.
1382 ///
1383 /// Returns field names in sorted order to ensure deterministic serialization
1384 /// and enable schema evolution.
1385 ///
1386 /// # Returns
1387 ///
1388 /// A static slice of field names in sorted order, or empty slice by default.
1389 ///
1390 /// # Implementation Notes
1391 ///
1392 /// - Implemented automatically by `#[derive(ForyStruct)]` macro
1393 /// - Used for field ordering and compatibility
1394 /// - Field order affects wire format
1395 /// - **Do not implement** for user types with custom serialization (EXT types)
1396 fn fory_get_sorted_field_names() -> &'static [&'static str] {
1397 &[]
1398 }
1399
1400 /// Deserialize a struct with schema compatibility support.
1401 ///
1402 /// This method enables reading structs even when the reader's schema differs
1403 /// from the writer's schema. It handles:
1404 ///
1405 /// - Missing fields (uses defaults)
1406 /// - Extra fields (skips them)
1407 /// - Reordered fields
1408 /// - Type changes (within compatibility rules)
1409 ///
1410 /// # Parameters
1411 ///
1412 /// * `context` - Read context with buffer and resolvers
1413 /// * `type_info` - Type metadata from the serialized data
1414 ///
1415 /// # Returns
1416 ///
1417 /// A deserialized instance with compatible field mapping.
1418 ///
1419 /// # Errors
1420 ///
1421 /// Returns an error if:
1422 ///
1423 /// - Required fields are missing without defaults
1424 /// - Field types are incompatible
1425 /// - Data is corrupted
1426 ///
1427 /// # Implementation Notes
1428 ///
1429 /// - Implemented automatically by `#[derive(ForyStruct)]` macro
1430 /// - Enables forward and backward compatibility
1431 /// - Uses field names for matching when possible
1432 /// - Falls back to field order for unnamed fields
1433 /// - **Do not implement** for user types with custom serialization (EXT types)
1434 fn fory_read_compatible(
1435 context: &mut ReadContext,
1436 type_info: Rc<TypeInfo>,
1437 ) -> Result<Self, Error>
1438 where
1439 Self: Sized;
1440}
1441
1442/// Serializes an object implementing `Serializer` to the write context.
1443///
1444/// This is a convenience wrapper around `T::fory_write_data` that delegates to the type's
1445/// serialization implementation.
1446#[inline(always)]
1447pub fn write_data<T: Serializer>(this: &T, context: &mut WriteContext) -> Result<(), Error> {
1448 T::fory_write_data(this, context)
1449}
1450
1451/// Deserializes an object implementing `Serializer` from the read context.
1452///
1453/// This is a convenience wrapper around `T::fory_read_data` that delegates to the type's
1454/// deserialization implementation. Requires `ForyDefault` for instance creation.
1455#[inline(always)]
1456pub fn read_data<T: Serializer + ForyDefault>(context: &mut ReadContext) -> Result<T, Error> {
1457 T::fory_read_data(context)
1458}