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