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