Skip to main content

fory_core/serializer/
tuple.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::resolver::RefMode;
21use crate::resolver::TypeResolver;
22use crate::serializer::collection::{read_collection_type_info, write_collection_type_info};
23use crate::serializer::skip::skip_any_value;
24use crate::serializer::{ForyDefault, Serializer};
25use crate::type_id::TypeId;
26use std::mem;
27
28// Unit type () implementation - represents an empty/unit value with no data
29impl Serializer for () {
30    #[inline(always)]
31    fn fory_write_data(&self, _context: &mut WriteContext) -> Result<(), Error> {
32        // Unit type has no data to write
33        Ok(())
34    }
35
36    #[inline(always)]
37    fn fory_read_data(_context: &mut ReadContext) -> Result<Self, Error> {
38        // Unit type has no data to read
39        Ok(())
40    }
41
42    #[inline(always)]
43    fn fory_reserved_space() -> usize {
44        0
45    }
46
47    #[inline(always)]
48    fn fory_get_type_id(_: &TypeResolver) -> Result<TypeId, Error> {
49        // Use NONE - unit type has no runtime data, skip can return early
50        Ok(TypeId::NONE)
51    }
52
53    #[inline(always)]
54    fn fory_type_id_dyn(&self, _: &TypeResolver) -> Result<TypeId, Error> {
55        // Use NONE - unit type has no runtime data, skip can return early
56        Ok(TypeId::NONE)
57    }
58
59    #[inline(always)]
60    fn fory_static_type_id() -> TypeId {
61        // Use NONE - unit type has no runtime data, skip can return early
62        TypeId::NONE
63    }
64
65    #[inline(always)]
66    fn as_any(&self) -> &dyn std::any::Any {
67        self
68    }
69}
70
71impl ForyDefault for () {
72    #[inline(always)]
73    fn fory_default() -> Self {}
74}
75
76/// Helper function to write a tuple element based on its type characteristics.
77/// This handles the different serialization strategies for various element types.
78#[inline(always)]
79fn write_tuple_element<T: Serializer>(elem: &T, context: &mut WriteContext) -> Result<(), Error> {
80    if T::fory_is_option() || T::fory_is_shared_ref() || T::fory_static_type_id() == TypeId::UNKNOWN
81    {
82        // For Option, shared references, or unknown static types, use full write with ref tracking
83        let ref_mode = if T::fory_is_shared_ref() {
84            RefMode::Tracking
85        } else {
86            RefMode::NullOnly
87        };
88        elem.fory_write(context, ref_mode, false, false)
89    } else {
90        // For concrete types with known static type IDs, directly write data
91        elem.fory_write_data(context)
92    }
93}
94
95/// Helper function to read a tuple element based on its type characteristics.
96#[inline(always)]
97fn read_tuple_element<T: Serializer + ForyDefault>(
98    context: &mut ReadContext,
99    _has_generics: bool,
100) -> Result<T, Error> {
101    if T::fory_is_option() || T::fory_is_shared_ref() || T::fory_static_type_id() == TypeId::UNKNOWN
102    {
103        // For Option, shared references, or unknown static types, use full read with ref tracking
104        let ref_mode = if T::fory_is_shared_ref() {
105            RefMode::Tracking
106        } else {
107            RefMode::NullOnly
108        };
109        T::fory_read(context, ref_mode, false)
110    } else {
111        // For concrete types with known static type IDs, directly read data
112        T::fory_read_data(context)
113    }
114}
115
116impl<T0: Serializer + ForyDefault> Serializer for (T0,) {
117    #[inline(always)]
118    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
119        if !context.is_compatible() && !context.is_xlang() {
120            // Non-compatible mode: write elements directly
121            write_tuple_element(&self.0, context)?;
122        } else {
123            // Compatible mode: use collection protocol (heterogeneous)
124            context.writer.write_var_u32(1);
125            let header = 0u8; // No IS_SAME_TYPE flag
126            context.writer.write_u8(header);
127            self.0.fory_write(context, RefMode::NullOnly, true, false)?;
128        }
129        Ok(())
130    }
131
132    #[inline(always)]
133    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
134        write_collection_type_info(context, TypeId::LIST as u32)
135    }
136
137    #[inline(always)]
138    fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
139        if !context.is_compatible() && !context.is_xlang() {
140            // Non-compatible mode: read elements directly
141            let elem0 = read_tuple_element::<T0>(context, false)?;
142            Ok((elem0,))
143        } else {
144            // Compatible mode: read collection protocol (heterogeneous)
145            let len = context.reader.read_var_u32()?;
146            let _header = context.reader.read_u8()?;
147
148            let elem0 = if len > 0 {
149                T0::fory_read(context, RefMode::NullOnly, true)?
150            } else {
151                T0::fory_default()
152            };
153
154            // Skip any extra elements beyond the first
155            for _ in 1..len {
156                skip_any_value(context, true)?;
157            }
158
159            Ok((elem0,))
160        }
161    }
162
163    #[inline(always)]
164    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
165        read_collection_type_info(context, TypeId::LIST as u32)
166    }
167
168    #[inline(always)]
169    fn fory_reserved_space() -> usize {
170        mem::size_of::<u32>()
171    }
172
173    #[inline(always)]
174    fn fory_get_type_id(_: &TypeResolver) -> Result<TypeId, Error> {
175        Ok(TypeId::LIST)
176    }
177
178    #[inline(always)]
179    fn fory_type_id_dyn(&self, _: &TypeResolver) -> Result<TypeId, Error> {
180        Ok(TypeId::LIST)
181    }
182
183    #[inline(always)]
184    fn fory_static_type_id() -> TypeId {
185        TypeId::LIST
186    }
187
188    #[inline(always)]
189    fn fory_is_wrapper_type() -> bool
190    where
191        Self: Sized,
192    {
193        true
194    }
195
196    #[inline(always)]
197    fn as_any(&self) -> &dyn std::any::Any {
198        self
199    }
200}
201
202impl<T0: ForyDefault> ForyDefault for (T0,) {
203    #[inline(always)]
204    fn fory_default() -> Self {
205        (T0::fory_default(),)
206    }
207}
208
209macro_rules! fory_tuple_field {
210    ($tuple:expr, T0) => {
211        $tuple.0
212    };
213    ($tuple:expr, T1) => {
214        $tuple.1
215    };
216    ($tuple:expr, T2) => {
217        $tuple.2
218    };
219    ($tuple:expr, T3) => {
220        $tuple.3
221    };
222    ($tuple:expr, T4) => {
223        $tuple.4
224    };
225    ($tuple:expr, T5) => {
226        $tuple.5
227    };
228    ($tuple:expr, T6) => {
229        $tuple.6
230    };
231    ($tuple:expr, T7) => {
232        $tuple.7
233    };
234    ($tuple:expr, T8) => {
235        $tuple.8
236    };
237    ($tuple:expr, T9) => {
238        $tuple.9
239    };
240    ($tuple:expr, T10) => {
241        $tuple.10
242    };
243    ($tuple:expr, T11) => {
244        $tuple.11
245    };
246    ($tuple:expr, T12) => {
247        $tuple.12
248    };
249    ($tuple:expr, T13) => {
250        $tuple.13
251    };
252    ($tuple:expr, T14) => {
253        $tuple.14
254    };
255    ($tuple:expr, T15) => {
256        $tuple.15
257    };
258    ($tuple:expr, T16) => {
259        $tuple.16
260    };
261    ($tuple:expr, T17) => {
262        $tuple.17
263    };
264    ($tuple:expr, T18) => {
265        $tuple.18
266    };
267    ($tuple:expr, T19) => {
268        $tuple.19
269    };
270    ($tuple:expr, T20) => {
271        $tuple.20
272    };
273    ($tuple:expr, T21) => {
274        $tuple.21
275    };
276    ($tuple:expr, T22) => {
277        $tuple.22
278    };
279    ($tuple:expr, T23) => {
280        $tuple.23
281    };
282    ($tuple:expr, T24) => {
283        $tuple.24
284    };
285    ($tuple:expr, T25) => {
286        $tuple.25
287    };
288    ($tuple:expr, T26) => {
289        $tuple.26
290    };
291    ($tuple:expr, T27) => {
292        $tuple.27
293    };
294    ($tuple:expr, T28) => {
295        $tuple.28
296    };
297    ($tuple:expr, T29) => {
298        $tuple.29
299    };
300    ($tuple:expr, T30) => {
301        $tuple.30
302    };
303    ($tuple:expr, T31) => {
304        $tuple.31
305    };
306    ($tuple:expr, T32) => {
307        $tuple.32
308    };
309    ($tuple:expr, T33) => {
310        $tuple.33
311    };
312    ($tuple:expr, T34) => {
313        $tuple.34
314    };
315    ($tuple:expr, T35) => {
316        $tuple.35
317    };
318    ($tuple:expr, T36) => {
319        $tuple.36
320    };
321    ($tuple:expr, T37) => {
322        $tuple.37
323    };
324    ($tuple:expr, T38) => {
325        $tuple.38
326    };
327    ($tuple:expr, T39) => {
328        $tuple.39
329    };
330    ($tuple:expr, T40) => {
331        $tuple.40
332    };
333}
334
335macro_rules! fory_tuple_count {
336    ($($name:ident),+ $(,)?) => {
337        0usize $(+ fory_tuple_count!(@one $name))*
338    };
339    (@one $name:ident) => { 1usize };
340}
341
342/// Macro to implement Serializer for tuples of various sizes.
343/// Fory supports tuples up to 22 elements, longer tuples are not allowed.
344///
345/// This handles two serialization modes:
346/// 1. Non-compatible mode: Write elements one by one without collection headers and type metadata
347/// 2. Compatible mode: Use full collection protocol with headers and type info (always heterogeneous)
348#[macro_export]
349macro_rules! impl_tuple_serializer {
350    // Multiple element tuples (2+)
351    ($T0:ident $(, $T:ident)+ $(,)?) => {
352        impl<$T0: Serializer + ForyDefault, $($T: Serializer + ForyDefault),*> Serializer for ($T0, $($T),*) {
353            #[inline(always)]
354            fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
355                if !context.is_compatible() && !context.is_xlang() {
356                    // Non-compatible mode: write elements directly one by one
357                    write_tuple_element(&self.0, context)?;
358                    $(
359                        write_tuple_element(&fory_tuple_field!(self, $T), context)?;
360                    )*
361                } else {
362                    // Compatible mode: use collection protocol (always heterogeneous)
363                    let len = fory_tuple_count!($T0, $($T),*);
364                    context.writer.write_var_u32(len as u32);
365
366                    // Write header without IS_SAME_TYPE flag
367                    let header = 0u8;
368                    context.writer.write_u8(header);
369
370                    // Write each element with its type info
371                    self.0.fory_write(context, RefMode::NullOnly, true, false)?;
372                    $(
373                        fory_tuple_field!(self, $T).fory_write(context, RefMode::NullOnly, true, false)?;
374                    )*
375                }
376                Ok(())
377            }
378
379            #[inline(always)]
380            fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
381                write_collection_type_info(context, TypeId::LIST as u32)
382            }
383
384            #[inline(always)]
385            fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
386                if !context.is_compatible() && !context.is_xlang() {
387                    // Non-compatible mode: read elements directly
388                    let elem0 = read_tuple_element::<$T0>(context, false)?;
389                    $(
390                        #[allow(non_snake_case)]
391                        let $T = read_tuple_element::<$T>(context, false)?;
392                    )*
393                    Ok((elem0, $($T),*))
394                } else {
395                    // Compatible mode: read collection protocol (always heterogeneous)
396                    // Handle flexible length: use defaults for missing elements, skip extras
397                    let len = context.reader.read_var_u32()?;
398                    let _header = context.reader.read_u8()?;
399
400                    // Track how many elements we've read
401                    let mut index = 0u32;
402
403                    // Read first element or use default
404                    let elem0 = if index < len {
405                        index += 1;
406                        $T0::fory_read(context, RefMode::NullOnly, true)?
407                    } else {
408                        $T0::fory_default()
409                    };
410
411                    // Read remaining elements or use defaults
412                    $(
413                        #[allow(non_snake_case)]
414                        let $T = if index < len {
415                            index += 1;
416                            $T::fory_read(context, RefMode::NullOnly, true)?
417                        } else {
418                            $T::fory_default()
419                        };
420                    )*
421
422                    // Skip any extra elements beyond what we expect
423                    for _ in index..len {
424                        skip_any_value(context, true)?;
425                    }
426
427                    Ok((elem0, $($T),*))
428                }
429            }
430
431            #[inline(always)]
432            fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
433                read_collection_type_info(context, TypeId::LIST as u32)
434            }
435
436            #[inline(always)]
437            fn fory_reserved_space() -> usize {
438                mem::size_of::<u32>() // Size for length
439            }
440
441            #[inline(always)]
442            fn fory_get_type_id(_: &TypeResolver) -> Result<TypeId, Error> {
443                Ok(TypeId::LIST)
444            }
445
446            #[inline(always)]
447            fn fory_type_id_dyn(&self, _: &TypeResolver) -> Result<TypeId, Error> {
448                Ok(TypeId::LIST)
449            }
450
451            #[inline(always)]
452            fn fory_static_type_id() -> TypeId {
453                TypeId::LIST
454            }
455
456            #[inline(always)]
457            fn fory_is_wrapper_type() -> bool
458                where
459                    Self: Sized, {
460                true
461            }
462
463            #[inline(always)]
464            fn as_any(&self) -> &dyn std::any::Any {
465                self
466            }
467        }
468
469        impl<$T0: ForyDefault, $($T: ForyDefault),*> ForyDefault for ($T0, $($T),*) {
470            #[inline(always)]
471            fn fory_default() -> Self {
472                ($T0::fory_default(), $($T::fory_default()),*)
473            }
474        }
475    };
476}
477
478// Implement Serializer for tuples of size 2-22
479impl_tuple_serializer!(T0, T1);
480impl_tuple_serializer!(T0, T1, T2);
481impl_tuple_serializer!(T0, T1, T2, T3);
482impl_tuple_serializer!(T0, T1, T2, T3, T4);
483impl_tuple_serializer!(T0, T1, T2, T3, T4, T5);
484impl_tuple_serializer!(T0, T1, T2, T3, T4, T5, T6);
485impl_tuple_serializer!(T0, T1, T2, T3, T4, T5, T6, T7);
486impl_tuple_serializer!(T0, T1, T2, T3, T4, T5, T6, T7, T8);
487impl_tuple_serializer!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
488impl_tuple_serializer!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
489impl_tuple_serializer!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
490impl_tuple_serializer!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
491impl_tuple_serializer!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
492impl_tuple_serializer!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
493impl_tuple_serializer!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
494impl_tuple_serializer!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);
495impl_tuple_serializer!(
496    T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17
497);
498impl_tuple_serializer!(
499    T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18
500);
501impl_tuple_serializer!(
502    T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19
503);
504impl_tuple_serializer!(
505    T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20
506);
507impl_tuple_serializer!(
508    T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20,
509    T21
510);