Skip to main content

fory_core/serializer/
map.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::ensure;
19use crate::error::Error;
20use crate::resolver::context::{ReadContext, WriteContext};
21use crate::resolver::type_resolver::{TypeInfo, TypeResolver};
22use crate::serializer::util::read_basic_type_info;
23use crate::serializer::{ForyDefault, Serializer};
24use crate::types::{need_to_write_type_for_field, RefMode, TypeId, SIZE_OF_REF_AND_TYPE};
25use std::collections::{BTreeMap, HashMap};
26use std::rc::Rc;
27
28const MAX_CHUNK_SIZE: u8 = 255;
29
30const TRACKING_KEY_REF: u8 = 0b1;
31pub const KEY_NULL: u8 = 0b10;
32pub const DECL_KEY_TYPE: u8 = 0b100;
33const TRACKING_VALUE_REF: u8 = 0b1000;
34pub const VALUE_NULL: u8 = 0b10000;
35pub const DECL_VALUE_TYPE: u8 = 0b100000;
36
37fn write_chunk_size(context: &mut WriteContext, header_offset: usize, size: u8) {
38    context.writer.set_bytes(header_offset + 1, &[size]);
39}
40
41pub fn write_map_data<'a, K, V, I>(
42    iter: I,
43    length: usize,
44    context: &mut WriteContext,
45    has_generics: bool,
46) -> Result<(), Error>
47where
48    K: Serializer,
49    V: Serializer,
50    I: Iterator<Item = (&'a K, &'a V)>,
51{
52    context.writer.write_var_uint32(length as u32);
53    if length == 0 {
54        return Ok(());
55    }
56    let reserved_space = (K::fory_reserved_space() + SIZE_OF_REF_AND_TYPE) * length
57        + (V::fory_reserved_space() + SIZE_OF_REF_AND_TYPE) * length;
58    context.writer.reserve(reserved_space);
59
60    if K::fory_is_polymorphic()
61        || K::fory_is_shared_ref()
62        || V::fory_is_polymorphic()
63        || V::fory_is_shared_ref()
64    {
65        return write_map_data_dyn_ref(iter, context, has_generics);
66    }
67    let mut header_offset = 0;
68    let mut pair_counter: u8 = 0;
69    let mut need_write_header = true;
70    let key_static_type_id = K::fory_static_type_id();
71    let val_static_type_id = V::fory_static_type_id();
72    let is_key_declared = has_generics && !need_to_write_type_for_field(key_static_type_id);
73    let is_val_declared = has_generics && !need_to_write_type_for_field(val_static_type_id);
74    for (key, value) in iter {
75        let key_is_none = key.fory_is_none();
76        let value_is_none = value.fory_is_none();
77
78        if key_is_none || value_is_none {
79            if !need_write_header && pair_counter > 0 {
80                write_chunk_size(context, header_offset, pair_counter);
81                pair_counter = 0;
82                need_write_header = true;
83            }
84
85            if key_is_none && value_is_none {
86                context.writer.write_u8(KEY_NULL | VALUE_NULL);
87                continue;
88            }
89
90            if value_is_none {
91                let mut chunk_header = VALUE_NULL;
92                if is_key_declared {
93                    chunk_header |= DECL_KEY_TYPE;
94                    context.writer.write_u8(chunk_header);
95                } else {
96                    context.writer.write_u8(chunk_header);
97                    K::fory_write_type_info(context)?;
98                }
99                key.fory_write_data_generic(context, has_generics)?;
100                continue;
101            }
102
103            // key is None, value is not
104            let mut chunk_header = KEY_NULL;
105            if is_val_declared {
106                chunk_header |= DECL_VALUE_TYPE;
107                context.writer.write_u8(chunk_header);
108            } else {
109                context.writer.write_u8(chunk_header);
110                V::fory_write_type_info(context)?;
111            }
112            value.fory_write_data_generic(context, has_generics)?;
113            continue;
114        }
115
116        if need_write_header {
117            header_offset = context.writer.len();
118            context.writer.write_i16(-1);
119            let mut chunk_header = 0u8;
120            if is_key_declared {
121                chunk_header |= DECL_KEY_TYPE;
122            } else {
123                K::fory_write_type_info(context)?;
124            }
125            if is_val_declared {
126                chunk_header |= DECL_VALUE_TYPE;
127            } else {
128                V::fory_write_type_info(context)?;
129            }
130            context.writer.set_bytes(header_offset, &[chunk_header]);
131            need_write_header = false;
132        }
133
134        key.fory_write_data_generic(context, has_generics)?;
135        value.fory_write_data_generic(context, has_generics)?;
136        pair_counter += 1;
137        if pair_counter == MAX_CHUNK_SIZE {
138            write_chunk_size(context, header_offset, pair_counter);
139            pair_counter = 0;
140            need_write_header = true;
141        }
142    }
143    if pair_counter > 0 {
144        write_chunk_size(context, header_offset, pair_counter);
145    }
146    Ok(())
147}
148
149/// slow but versatile map serialization for dynamic trait object and shared/circular reference.
150fn write_map_data_dyn_ref<'a, K, V, I>(
151    iter: I,
152    context: &mut WriteContext,
153    has_generics: bool,
154) -> Result<(), Error>
155where
156    K: Serializer,
157    V: Serializer,
158    I: Iterator<Item = (&'a K, &'a V)>,
159{
160    let mut header_offset = 0;
161    let mut pair_counter: u8 = 0;
162    let mut need_write_header = true;
163    let key_static_type_id = K::fory_static_type_id();
164    let val_static_type_id = V::fory_static_type_id();
165    let is_key_declared = has_generics && !need_to_write_type_for_field(key_static_type_id);
166    let is_val_declared = has_generics && !need_to_write_type_for_field(val_static_type_id);
167    let key_is_polymorphic = K::fory_is_polymorphic();
168    let val_is_polymorphic = V::fory_is_polymorphic();
169    let key_is_shared_ref = K::fory_is_shared_ref();
170    let val_is_shared_ref = V::fory_is_shared_ref();
171
172    // Track the current chunk's key and value types (for polymorphic types)
173    let mut current_key_type_id: Option<std::any::TypeId> = None;
174    let mut current_val_type_id: Option<std::any::TypeId> = None;
175
176    for (key, value) in iter {
177        // Handle null key/value entries (write as separate single-entry chunks)
178        if key.fory_is_none() || value.fory_is_none() {
179            // Finish current chunk if any
180            if pair_counter > 0 {
181                write_chunk_size(context, header_offset, pair_counter);
182                pair_counter = 0;
183                need_write_header = true;
184            }
185
186            if key.fory_is_none() && value.fory_is_none() {
187                context.writer.write_u8(KEY_NULL | VALUE_NULL);
188                continue;
189            } else if value.fory_is_none() {
190                let mut chunk_header = VALUE_NULL;
191                if key_is_shared_ref {
192                    chunk_header |= TRACKING_KEY_REF;
193                }
194                if is_key_declared && !key_is_polymorphic {
195                    chunk_header |= DECL_KEY_TYPE;
196                    context.writer.write_u8(chunk_header);
197                } else {
198                    context.writer.write_u8(chunk_header);
199                    if key_is_polymorphic {
200                        context.write_any_type_info(
201                            K::fory_static_type_id() as u32,
202                            key.fory_concrete_type_id(),
203                        )?;
204                    } else {
205                        K::fory_write_type_info(context)?;
206                    }
207                }
208                if key_is_shared_ref {
209                    key.fory_write(context, RefMode::Tracking, false, has_generics)?;
210                } else {
211                    key.fory_write_data_generic(context, has_generics)?;
212                }
213                continue;
214            } else {
215                // key.fory_is_none()
216                let mut chunk_header = KEY_NULL;
217                if val_is_shared_ref {
218                    chunk_header |= TRACKING_VALUE_REF;
219                }
220                if is_val_declared && !val_is_polymorphic {
221                    chunk_header |= DECL_VALUE_TYPE;
222                    context.writer.write_u8(chunk_header);
223                } else {
224                    context.writer.write_u8(chunk_header);
225                    if val_is_polymorphic {
226                        context.write_any_type_info(
227                            V::fory_static_type_id() as u32,
228                            value.fory_concrete_type_id(),
229                        )?;
230                    } else {
231                        V::fory_write_type_info(context)?;
232                    }
233                }
234                if val_is_shared_ref {
235                    value.fory_write(context, RefMode::Tracking, false, has_generics)?;
236                } else {
237                    value.fory_write_data_generic(context, has_generics)?;
238                }
239                continue;
240            }
241        }
242
243        // Get type IDs for polymorphic types
244        let key_type_id = if key_is_polymorphic {
245            Some(key.fory_concrete_type_id())
246        } else {
247            None
248        };
249        let val_type_id = if val_is_polymorphic {
250            Some(value.fory_concrete_type_id())
251        } else {
252            None
253        };
254
255        // Check if we need to start a new chunk due to type changes
256        let types_changed = if key_is_polymorphic || val_is_polymorphic {
257            key_type_id != current_key_type_id || val_type_id != current_val_type_id
258        } else {
259            false
260        };
261
262        if need_write_header || types_changed {
263            // Finish previous chunk if types changed
264            if types_changed && pair_counter > 0 {
265                write_chunk_size(context, header_offset, pair_counter);
266                pair_counter = 0;
267            }
268
269            // Write new chunk header
270            header_offset = context.writer.len();
271            context.writer.write_i16(-1); // Placeholder for header and size
272
273            let mut chunk_header = 0u8;
274
275            // Set key flags
276            if key_is_shared_ref {
277                chunk_header |= TRACKING_KEY_REF;
278            }
279            if is_key_declared && !key_is_polymorphic {
280                chunk_header |= DECL_KEY_TYPE;
281            } else {
282                // Write type info for key
283                if key_is_polymorphic {
284                    context.write_any_type_info(
285                        K::fory_static_type_id() as u32,
286                        key.fory_concrete_type_id(),
287                    )?;
288                } else {
289                    K::fory_write_type_info(context)?;
290                }
291            }
292
293            // Set value flags
294            if val_is_shared_ref {
295                chunk_header |= TRACKING_VALUE_REF;
296            }
297            if is_val_declared && !val_is_polymorphic {
298                chunk_header |= DECL_VALUE_TYPE;
299            } else {
300                // Write type info for value
301                if val_is_polymorphic {
302                    context.write_any_type_info(
303                        V::fory_static_type_id() as u32,
304                        value.fory_concrete_type_id(),
305                    )?;
306                } else {
307                    V::fory_write_type_info(context)?;
308                }
309            }
310
311            context.writer.set_bytes(header_offset, &[chunk_header]);
312            need_write_header = false;
313            current_key_type_id = key_type_id;
314            current_val_type_id = val_type_id;
315        }
316
317        // Write key-value pair
318        if key_is_shared_ref {
319            key.fory_write(context, RefMode::Tracking, false, has_generics)?;
320        } else {
321            key.fory_write_data_generic(context, has_generics)?;
322        }
323        if val_is_shared_ref {
324            value.fory_write(context, RefMode::Tracking, false, has_generics)?;
325        } else {
326            value.fory_write_data_generic(context, has_generics)?;
327        }
328        pair_counter += 1;
329        if pair_counter == MAX_CHUNK_SIZE {
330            write_chunk_size(context, header_offset, pair_counter);
331            pair_counter = 0;
332            need_write_header = true;
333            current_key_type_id = None;
334            current_val_type_id = None;
335        }
336    }
337
338    // Write final chunk size if any
339    if pair_counter > 0 {
340        write_chunk_size(context, header_offset, pair_counter);
341    }
342
343    Ok(())
344}
345
346/// Macro to generate read_*_data_dyn_ref functions for HashMap and BTreeMap.
347/// This avoids code duplication while maintaining zero runtime cost.
348macro_rules! impl_read_map_dyn_ref {
349    ($fn_name:ident, $map_type:ty, $($extra_trait_bounds:tt)*) => {
350        fn $fn_name<K, V>(
351            context: &mut ReadContext,
352            mut map: $map_type,
353            length: u32,
354        ) -> Result<$map_type, Error>
355        where
356            K: Serializer + ForyDefault + $($extra_trait_bounds)*,
357            V: Serializer + ForyDefault,
358        {
359            let key_is_polymorphic = K::fory_is_polymorphic();
360            let val_is_polymorphic = V::fory_is_polymorphic();
361            let mut len_counter = 0u32;
362
363            while len_counter < length {
364                let header = context.reader.read_u8()?;
365
366                // Handle null key/value entries
367                if header & KEY_NULL != 0 && header & VALUE_NULL != 0 {
368                    // Both key and value are null
369                    map.insert(K::fory_default(), V::fory_default());
370                    len_counter += 1;
371                    continue;
372                }
373
374                if header & KEY_NULL != 0 {
375                    // Null key, non-null value
376                    let value_declared = (header & DECL_VALUE_TYPE) != 0;
377                    let track_value_ref = (header & TRACKING_VALUE_REF) != 0;
378
379                    // Determine value type info (if any)
380                    let value_type_info: Option<Rc<TypeInfo>> = if !value_declared {
381                        if val_is_polymorphic {
382                            Some(context.read_any_type_info()?)
383                        } else {
384                            V::fory_read_type_info(context)?;
385                            None
386                        }
387                    } else {
388                        None
389                    };
390
391                    // Read value payload
392                    let ref_mode = if track_value_ref {
393                        RefMode::Tracking
394                    } else {
395                        RefMode::None
396                    };
397                    let value = if let Some(type_info) = value_type_info {
398                        V::fory_read_with_type_info(context, ref_mode, type_info)?
399                    } else if track_value_ref {
400                        V::fory_read(context, ref_mode, false)?
401                    } else {
402                        V::fory_read_data(context)?
403                    };
404
405                    map.insert(K::fory_default(), value);
406                    len_counter += 1;
407                    continue;
408                }
409
410                if header & VALUE_NULL != 0 {
411                    // Non-null key, null value
412                    let key_declared = (header & DECL_KEY_TYPE) != 0;
413                    let track_key_ref = (header & TRACKING_KEY_REF) != 0;
414
415                    let key_type_info: Option<Rc<TypeInfo>> = if !key_declared {
416                        if key_is_polymorphic {
417                            Some(context.read_any_type_info()?)
418                        } else {
419                            K::fory_read_type_info(context)?;
420                            None
421                        }
422                    } else {
423                        None
424                    };
425
426                    let ref_mode = if track_key_ref {
427                        RefMode::Tracking
428                    } else {
429                        RefMode::None
430                    };
431                    let key = if let Some(type_info) = key_type_info {
432                        K::fory_read_with_type_info(context, ref_mode, type_info)?
433                    } else if track_key_ref {
434                        K::fory_read(context, ref_mode, false)?
435                    } else {
436                        K::fory_read_data(context)?
437                    };
438
439                    map.insert(key, V::fory_default());
440                    len_counter += 1;
441                    continue;
442                }
443
444                // Non-null key and value chunk
445                let chunk_size = context.reader.read_u8()?;
446                let key_declared = (header & DECL_KEY_TYPE) != 0;
447                let value_declared = (header & DECL_VALUE_TYPE) != 0;
448                let track_key_ref = (header & TRACKING_KEY_REF) != 0;
449                let track_value_ref = (header & TRACKING_VALUE_REF) != 0;
450
451                let key_type_info: Option<Rc<TypeInfo>> = if !key_declared {
452                    if key_is_polymorphic {
453                        Some(context.read_any_type_info()?)
454                    } else {
455                        K::fory_read_type_info(context)?;
456                        None
457                    }
458                } else {
459                    None
460                };
461                let value_type_info: Option<Rc<TypeInfo>> = if !value_declared {
462                    if val_is_polymorphic {
463                        Some(context.read_any_type_info()?)
464                    } else {
465                        V::fory_read_type_info(context)?;
466                        None
467                    }
468                } else {
469                    None
470                };
471
472                let cur_len = len_counter + chunk_size as u32;
473                ensure!(
474                    cur_len <= length,
475                    Error::invalid_data(
476                        format!("current length {} exceeds total length {}", cur_len, length)
477                    )
478                );
479
480                // Read chunk_size pairs of key-value
481                let key_ref_mode = if track_key_ref {
482                    RefMode::Tracking
483                } else {
484                    RefMode::None
485                };
486                let val_ref_mode = if track_value_ref {
487                    RefMode::Tracking
488                } else {
489                    RefMode::None
490                };
491                for _ in 0..chunk_size {
492                    let key = if let Some(type_info) = key_type_info.as_ref() {
493                        K::fory_read_with_type_info(context, key_ref_mode, type_info.clone())?
494                    } else if track_key_ref {
495                        K::fory_read(context, key_ref_mode, false)?
496                    } else {
497                        K::fory_read_data(context)?
498                    };
499
500                    let value = if let Some(type_info) = value_type_info.as_ref() {
501                        V::fory_read_with_type_info(context, val_ref_mode, type_info.clone())?
502                    } else if track_value_ref {
503                        V::fory_read(context, val_ref_mode, false)?
504                    } else {
505                        V::fory_read_data(context)?
506                    };
507
508                    map.insert(key, value);
509                }
510
511                len_counter += chunk_size as u32;
512            }
513
514            Ok(map)
515        }
516    };
517}
518
519// Generate read_hashmap_data_dyn_ref for HashMap
520impl_read_map_dyn_ref!(
521    read_hashmap_data_dyn_ref,
522    HashMap<K, V>,
523    Eq + std::hash::Hash
524);
525
526// Generate read_btreemap_data_dyn_ref for BTreeMap
527impl_read_map_dyn_ref!(
528    read_btreemap_data_dyn_ref,
529    BTreeMap<K, V>,
530    Ord
531);
532
533impl<K: Serializer + ForyDefault + Eq + std::hash::Hash, V: Serializer + ForyDefault> Serializer
534    for HashMap<K, V>
535{
536    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
537        write_map_data(self.iter(), self.len(), context, false)
538    }
539
540    fn fory_write_data_generic(
541        &self,
542        context: &mut WriteContext,
543        has_generics: bool,
544    ) -> Result<(), Error> {
545        write_map_data(self.iter(), self.len(), context, has_generics)
546    }
547
548    fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
549        let len = context.reader.read_varuint32()?;
550        let mut map = HashMap::<K, V>::with_capacity(len as usize);
551        if len == 0 {
552            return Ok(map);
553        }
554        if K::fory_is_polymorphic()
555            || K::fory_is_shared_ref()
556            || V::fory_is_polymorphic()
557            || V::fory_is_shared_ref()
558        {
559            let map: HashMap<K, V> = HashMap::with_capacity(len as usize);
560            return read_hashmap_data_dyn_ref(context, map, len);
561        }
562        let mut len_counter = 0;
563        loop {
564            if len_counter == len {
565                break;
566            }
567            let header = context.reader.read_u8()?;
568            if header & KEY_NULL != 0 && header & VALUE_NULL != 0 {
569                map.insert(K::fory_default(), V::fory_default());
570                len_counter += 1;
571                continue;
572            }
573            let key_declared = (header & DECL_KEY_TYPE) != 0;
574            let value_declared = (header & DECL_VALUE_TYPE) != 0;
575            let track_key_ref = (header & TRACKING_KEY_REF) != 0;
576            let track_value_ref = (header & TRACKING_VALUE_REF) != 0;
577            if header & KEY_NULL != 0 {
578                // Null case is handled by KEY_NULL flag, so use None (no ref flag) unless tracking
579                let ref_mode = if track_value_ref {
580                    RefMode::Tracking
581                } else {
582                    RefMode::None
583                };
584                let value = V::fory_read(context, ref_mode, !value_declared)?;
585                map.insert(K::fory_default(), value);
586                len_counter += 1;
587                continue;
588            }
589            if header & VALUE_NULL != 0 {
590                // Null case is handled by VALUE_NULL flag, so use None (no ref flag) unless tracking
591                let ref_mode = if track_key_ref {
592                    RefMode::Tracking
593                } else {
594                    RefMode::None
595                };
596                let key = K::fory_read(context, ref_mode, !key_declared)?;
597                map.insert(key, V::fory_default());
598                len_counter += 1;
599                continue;
600            }
601            let chunk_size = context.reader.read_u8()?;
602            if header & DECL_KEY_TYPE == 0 {
603                K::fory_read_type_info(context)?;
604            }
605            if header & DECL_VALUE_TYPE == 0 {
606                V::fory_read_type_info(context)?;
607            }
608            let cur_len = len_counter + chunk_size as u32;
609            ensure!(
610                cur_len <= len,
611                Error::invalid_data(format!(
612                    "current length {} exceeds total length {}",
613                    cur_len, len
614                ))
615            );
616            if !track_key_ref && !track_value_ref {
617                for _ in 0..chunk_size {
618                    let key = K::fory_read_data(context)?;
619                    let value = V::fory_read_data(context)?;
620                    map.insert(key, value);
621                }
622            } else {
623                let key_ref_mode = if track_key_ref {
624                    RefMode::Tracking
625                } else {
626                    RefMode::None
627                };
628                let val_ref_mode = if track_value_ref {
629                    RefMode::Tracking
630                } else {
631                    RefMode::None
632                };
633                for _ in 0..chunk_size {
634                    let key = K::fory_read(context, key_ref_mode, false)?;
635                    let value = V::fory_read(context, val_ref_mode, false)?;
636                    map.insert(key, value);
637                }
638            }
639            // advance the counter after processing the chunk
640            len_counter += chunk_size as u32;
641        }
642        Ok(map)
643    }
644
645    fn fory_reserved_space() -> usize {
646        size_of::<i32>()
647    }
648
649    fn fory_get_type_id(_: &TypeResolver) -> Result<TypeId, Error> {
650        Ok(TypeId::MAP)
651    }
652
653    fn fory_type_id_dyn(&self, _: &TypeResolver) -> Result<TypeId, Error> {
654        Ok(TypeId::MAP)
655    }
656
657    fn fory_static_type_id() -> TypeId
658    where
659        Self: Sized,
660    {
661        TypeId::MAP
662    }
663
664    fn as_any(&self) -> &dyn std::any::Any {
665        self
666    }
667
668    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
669        context.writer.write_u8(TypeId::MAP as u8);
670        Ok(())
671    }
672
673    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
674        read_basic_type_info::<Self>(context)
675    }
676}
677
678impl<K, V> ForyDefault for HashMap<K, V> {
679    fn fory_default() -> Self {
680        HashMap::new()
681    }
682}
683
684impl<K: Serializer + ForyDefault + Ord + std::hash::Hash, V: Serializer + ForyDefault> Serializer
685    for BTreeMap<K, V>
686{
687    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
688        write_map_data(self.iter(), self.len(), context, false)
689    }
690
691    fn fory_write_data_generic(
692        &self,
693        context: &mut WriteContext,
694        has_generics: bool,
695    ) -> Result<(), Error> {
696        write_map_data(self.iter(), self.len(), context, has_generics)
697    }
698
699    fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
700        let len = context.reader.read_varuint32()?;
701        let mut map = BTreeMap::<K, V>::new();
702        if len == 0 {
703            return Ok(map);
704        }
705        if K::fory_is_polymorphic()
706            || K::fory_is_shared_ref()
707            || V::fory_is_polymorphic()
708            || V::fory_is_shared_ref()
709        {
710            let map: BTreeMap<K, V> = BTreeMap::new();
711            return read_btreemap_data_dyn_ref(context, map, len);
712        }
713        let mut len_counter = 0;
714        loop {
715            if len_counter == len {
716                break;
717            }
718            let header = context.reader.read_u8()?;
719            if header & KEY_NULL != 0 && header & VALUE_NULL != 0 {
720                map.insert(K::fory_default(), V::fory_default());
721                len_counter += 1;
722                continue;
723            }
724            let key_declared = (header & DECL_KEY_TYPE) != 0;
725            let value_declared = (header & DECL_VALUE_TYPE) != 0;
726            let track_key_ref = (header & TRACKING_KEY_REF) != 0;
727            let track_value_ref = (header & TRACKING_VALUE_REF) != 0;
728            if header & KEY_NULL != 0 {
729                // Null case is handled by KEY_NULL flag, so use None (no ref flag) unless tracking
730                let ref_mode = if track_value_ref {
731                    RefMode::Tracking
732                } else {
733                    RefMode::None
734                };
735                let value = V::fory_read(context, ref_mode, !value_declared)?;
736                map.insert(K::fory_default(), value);
737                len_counter += 1;
738                continue;
739            }
740            if header & VALUE_NULL != 0 {
741                // Null case is handled by VALUE_NULL flag, so use None (no ref flag) unless tracking
742                let ref_mode = if track_key_ref {
743                    RefMode::Tracking
744                } else {
745                    RefMode::None
746                };
747                let key = K::fory_read(context, ref_mode, !key_declared)?;
748                map.insert(key, V::fory_default());
749                len_counter += 1;
750                continue;
751            }
752            let chunk_size = context.reader.read_u8()?;
753            if header & DECL_KEY_TYPE == 0 {
754                K::fory_read_type_info(context)?;
755            }
756            if header & DECL_VALUE_TYPE == 0 {
757                V::fory_read_type_info(context)?;
758            }
759            let cur_len = len_counter + chunk_size as u32;
760            ensure!(
761                cur_len <= len,
762                Error::invalid_data(format!(
763                    "current length {} exceeds total length {}",
764                    cur_len, len
765                ))
766            );
767            if !track_key_ref && !track_value_ref {
768                for _ in 0..chunk_size {
769                    let key = K::fory_read_data(context)?;
770                    let value = V::fory_read_data(context)?;
771                    map.insert(key, value);
772                }
773            } else {
774                let key_ref_mode = if track_key_ref {
775                    RefMode::Tracking
776                } else {
777                    RefMode::None
778                };
779                let val_ref_mode = if track_value_ref {
780                    RefMode::Tracking
781                } else {
782                    RefMode::None
783                };
784                for _ in 0..chunk_size {
785                    let key = K::fory_read(context, key_ref_mode, false)?;
786                    let value = V::fory_read(context, val_ref_mode, false)?;
787                    map.insert(key, value);
788                }
789            }
790            len_counter += chunk_size as u32;
791        }
792        Ok(map)
793    }
794
795    fn fory_reserved_space() -> usize {
796        size_of::<i32>()
797    }
798
799    fn fory_get_type_id(_: &TypeResolver) -> Result<TypeId, Error> {
800        Ok(TypeId::MAP)
801    }
802
803    fn fory_type_id_dyn(&self, _: &TypeResolver) -> Result<TypeId, Error> {
804        Ok(TypeId::MAP)
805    }
806
807    fn fory_static_type_id() -> TypeId
808    where
809        Self: Sized,
810    {
811        TypeId::MAP
812    }
813
814    fn as_any(&self) -> &dyn std::any::Any {
815        self
816    }
817
818    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
819        context.writer.write_u8(TypeId::MAP as u8);
820        Ok(())
821    }
822
823    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
824        read_basic_type_info::<Self>(context)
825    }
826}
827
828impl<K, V> ForyDefault for BTreeMap<K, V> {
829    fn fory_default() -> Self {
830        BTreeMap::new()
831    }
832}