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