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