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