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