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 super::codec::{
19    field_ref_mode, field_type_with_ref_flags, generic_field_type, Codec, CodecReadType,
20};
21use super::collection::check_count_write_bytes;
22use crate::context::{ReadContext, WriteContext};
23use crate::error::Error;
24use crate::meta::FieldType;
25use crate::resolver::{RefFlag, RefMode, TypeInfo, TypeResolver};
26use crate::serializer::{core::read_value_type_info, Serializer};
27use crate::type_id::{need_to_write_type_for_field, TypeId, SIZE_OF_REF_AND_TYPE};
28use std::borrow::Cow;
29use std::collections::{BTreeMap, HashMap};
30use std::marker::PhantomData;
31use std::rc::Rc;
32
33const MAX_CHUNK_SIZE: u8 = 255;
34pub(crate) const TRACKING_KEY_REF: u8 = 0b1;
35pub(crate) const KEY_NULL: u8 = 0b10;
36pub(crate) const DECL_KEY_TYPE: u8 = 0b100;
37pub(crate) const TRACKING_VALUE_REF: u8 = 0b1000;
38pub(crate) const VALUE_NULL: u8 = 0b10000;
39pub(crate) const DECL_VALUE_TYPE: u8 = 0b100000;
40
41pub struct BTreeMapCodec<K, V, KC, VC, const NULLABLE: bool, const TRACK_REF: bool>(
42    PhantomData<(K, V, KC, VC)>,
43);
44
45pub struct HashMapCodec<K, V, KC, VC, const NULLABLE: bool, const TRACK_REF: bool>(
46    PhantomData<(K, V, KC, VC)>,
47);
48
49trait MapTarget<K, V>: Sized {
50    fn with_capacity(capacity: usize) -> Self;
51    fn insert(&mut self, key: K, value: V);
52}
53
54impl<K: Eq + std::hash::Hash, V> MapTarget<K, V> for HashMap<K, V> {
55    #[inline(always)]
56    fn with_capacity(capacity: usize) -> Self {
57        HashMap::with_capacity(capacity)
58    }
59
60    #[inline(always)]
61    fn insert(&mut self, key: K, value: V) {
62        HashMap::insert(self, key, value);
63    }
64}
65
66impl<K: Ord, V> MapTarget<K, V> for BTreeMap<K, V> {
67    #[inline(always)]
68    fn with_capacity(_: usize) -> Self {
69        BTreeMap::new()
70    }
71
72    #[inline(always)]
73    fn insert(&mut self, key: K, value: V) {
74        BTreeMap::insert(self, key, value);
75    }
76}
77
78#[inline(always)]
79fn write_entry_type<T: 'static, S: Serializer<Target = T>>(
80    context: &mut WriteContext,
81    target_type_id: Option<std::any::TypeId>,
82) -> Result<Option<Rc<TypeInfo>>, Error> {
83    if let Some(target_type_id) = target_type_id {
84        S::write_type_info_value(context, target_type_id).map(Some)
85    } else {
86        S::write_type_info(context)?;
87        Ok(None)
88    }
89}
90
91macro_rules! map_write_mode {
92    (value, $T:ty, $S:ty, $value:expr, $context:expr, $ref_mode:expr, $write_type:expr, $has_generics:expr) => {
93        <$S as Serializer>::write($value, $context, $ref_mode, $write_type)
94    };
95    (field, $T:ty, $C:ty, $value:expr, $context:expr, $ref_mode:expr, $write_type:expr, $has_generics:expr) => {
96        <$C as Codec<$T>>::write_with_mode($value, $context, $ref_mode, $write_type, $has_generics)
97    };
98}
99
100macro_rules! map_write_with_info {
101    (value, $T:ty, $S:ty, $value:expr, $context:expr, $ref_mode:expr, $type_info:expr, $has_generics:expr) => {
102        <$S as Serializer>::write_with_type_info($value, $context, $ref_mode, $type_info)
103    };
104    (field, $T:ty, $C:ty, $value:expr, $context:expr, $ref_mode:expr, $type_info:expr, $has_generics:expr) => {
105        <$C as Codec<$T>>::write_with_type_info(
106            $value,
107            $context,
108            $ref_mode,
109            $type_info,
110            $has_generics,
111        )
112    };
113}
114
115macro_rules! map_write_entry {
116    ($layer:ident, $T:ty, $C:ty, $value:expr, $context:expr, $track_ref:expr, $has_generics:expr, $type_info:expr) => {{
117        let ref_mode = if $track_ref {
118            RefMode::Tracking
119        } else {
120            RefMode::None
121        };
122        if let Some(type_info) = $type_info {
123            map_write_with_info!(
124                $layer,
125                $T,
126                $C,
127                $value,
128                $context,
129                ref_mode,
130                type_info,
131                $has_generics
132            )
133        } else {
134            map_write_mode!(
135                $layer,
136                $T,
137                $C,
138                $value,
139                $context,
140                ref_mode,
141                false,
142                $has_generics
143            )
144        }
145    }};
146}
147
148macro_rules! map_reserved_space {
149    (value, $T:ty, $S:ty) => {
150        <$S as Serializer>::reserved_space()
151    };
152    (field, $T:ty, $C:ty) => {
153        <$C as Codec<$T>>::field_reserved_space()
154    };
155}
156
157macro_rules! write_map_data_body {
158    (
159        $layer:ident,
160        $K:ident,
161        $V:ident,
162        $KC:ident,
163        $VC:ident,
164        $iter:expr,
165        $len:expr,
166        $context:expr,
167        $has_generics:expr
168    ) => {{
169        let context = $context;
170        let len = $len;
171        context.writer.write_var_u32(len as u32);
172        if len == 0 {
173            return Ok(());
174        }
175        let body_offset = context.writer.len();
176        context.writer.reserve(
177            len.saturating_mul(
178                map_reserved_space!($layer, $K, $KC)
179                    .saturating_add(map_reserved_space!($layer, $V, $VC)),
180            ),
181        );
182
183        let has_generics = $has_generics;
184        let key_declared = has_generics && !need_to_write_type_for_field($KC::static_type_id());
185        let value_declared = has_generics && !need_to_write_type_for_field($VC::static_type_id());
186        let key_polymorphic = $KC::IS_POLYMORPHIC;
187        let value_polymorphic = $VC::IS_POLYMORPHIC;
188        let key_shared = $KC::IS_SHARED_REF;
189        let value_shared = $VC::IS_SHARED_REF;
190        let mut key_type = None;
191        let mut value_type = None;
192        let mut key_info = None;
193        let mut value_info = None;
194        let mut header_offset = 0;
195        let mut pair_count = 0u8;
196        let mut need_header = true;
197
198        for (key, value) in $iter {
199            // MAP emits both type headers before either body. Holder serializers
200            // release this inspection immediately; resolved body writes
201            // revalidate the value, so matching entries can still share one
202            // chunk TypeInfo.
203            let next_key_type = if key_polymorphic {
204                $KC::dynamic_type_id(key)?
205            } else {
206                None
207            };
208            let next_value_type = if value_polymorphic {
209                $VC::dynamic_type_id(value)?
210            } else {
211                None
212            };
213            let key_none = if key_polymorphic {
214                next_key_type.is_none()
215            } else {
216                $KC::is_none(key)
217            };
218            let value_none = if value_polymorphic {
219                next_value_type.is_none()
220            } else {
221                $VC::is_none(value)
222            };
223            if key_none || value_none {
224                if pair_count != 0 {
225                    context.writer.set_bytes(header_offset + 1, &[pair_count]);
226                    pair_count = 0;
227                    need_header = true;
228                }
229                if key_none && value_none {
230                    context.writer.write_u8(KEY_NULL | VALUE_NULL);
231                    continue;
232                }
233                if value_none {
234                    let mut header = VALUE_NULL;
235                    if key_shared {
236                        header |= TRACKING_KEY_REF;
237                    }
238                    if key_declared && !key_polymorphic {
239                        header |= DECL_KEY_TYPE;
240                        context.writer.write_u8(header);
241                        map_write_entry!(
242                            $layer,
243                            $K,
244                            $KC,
245                            key,
246                            context,
247                            key_shared,
248                            has_generics,
249                            None
250                        )?;
251                    } else {
252                        context.writer.write_u8(header);
253                        if key_shared {
254                            map_write_mode!(
255                                $layer,
256                                $K,
257                                $KC,
258                                key,
259                                context,
260                                RefMode::Tracking,
261                                true,
262                                has_generics
263                            )?;
264                        } else {
265                            let key_info = write_entry_type::<$K, $KC>(context, next_key_type)?;
266                            map_write_entry!(
267                                $layer,
268                                $K,
269                                $KC,
270                                key,
271                                context,
272                                false,
273                                has_generics,
274                                key_info.as_ref()
275                            )?;
276                        }
277                    }
278                    continue;
279                }
280                let mut header = KEY_NULL;
281                if value_shared {
282                    header |= TRACKING_VALUE_REF;
283                }
284                if value_declared && !value_polymorphic {
285                    header |= DECL_VALUE_TYPE;
286                    context.writer.write_u8(header);
287                    map_write_entry!(
288                        $layer,
289                        $V,
290                        $VC,
291                        value,
292                        context,
293                        value_shared,
294                        has_generics,
295                        None
296                    )?;
297                } else {
298                    context.writer.write_u8(header);
299                    if value_shared {
300                        map_write_mode!(
301                            $layer,
302                            $V,
303                            $VC,
304                            value,
305                            context,
306                            RefMode::Tracking,
307                            true,
308                            has_generics
309                        )?;
310                    } else {
311                        let value_info = write_entry_type::<$V, $VC>(context, next_value_type)?;
312                        map_write_entry!(
313                            $layer,
314                            $V,
315                            $VC,
316                            value,
317                            context,
318                            false,
319                            has_generics,
320                            value_info.as_ref()
321                        )?;
322                    }
323                }
324                continue;
325            }
326
327            let types_changed = (key_polymorphic || value_polymorphic)
328                && (next_key_type != key_type || next_value_type != value_type);
329            if need_header || types_changed {
330                if pair_count != 0 {
331                    context.writer.set_bytes(header_offset + 1, &[pair_count]);
332                    pair_count = 0;
333                }
334                header_offset = context.writer.len();
335                context.writer.write_i16(-1);
336                let mut header = 0;
337                if key_shared {
338                    header |= TRACKING_KEY_REF;
339                }
340                if value_shared {
341                    header |= TRACKING_VALUE_REF;
342                }
343                if key_declared && !key_polymorphic {
344                    header |= DECL_KEY_TYPE;
345                    key_info = None;
346                } else {
347                    key_info = write_entry_type::<$K, $KC>(context, next_key_type)?;
348                }
349                if value_declared && !value_polymorphic {
350                    header |= DECL_VALUE_TYPE;
351                    value_info = None;
352                } else {
353                    value_info = write_entry_type::<$V, $VC>(context, next_value_type)?;
354                }
355                context.writer.set_bytes(header_offset, &[header]);
356                need_header = false;
357                key_type = next_key_type;
358                value_type = next_value_type;
359            }
360
361            map_write_entry!(
362                $layer,
363                $K,
364                $KC,
365                key,
366                context,
367                key_shared,
368                has_generics,
369                key_info.as_ref()
370            )?;
371            map_write_entry!(
372                $layer,
373                $V,
374                $VC,
375                value,
376                context,
377                value_shared,
378                has_generics,
379                value_info.as_ref()
380            )?;
381            pair_count += 1;
382            if pair_count == MAX_CHUNK_SIZE {
383                context.writer.set_bytes(header_offset + 1, &[pair_count]);
384                pair_count = 0;
385                need_header = true;
386                key_type = None;
387                value_type = None;
388                key_info = None;
389                value_info = None;
390            }
391        }
392        if pair_count != 0 {
393            context.writer.set_bytes(header_offset + 1, &[pair_count]);
394        }
395        check_count_write_bytes(context, body_offset, len)
396    }};
397}
398
399fn write_value_map_data<'a, K, V, KS, VS, I>(
400    iter: I,
401    len: usize,
402    context: &mut WriteContext,
403) -> Result<(), Error>
404where
405    K: 'static + 'a,
406    V: 'static + 'a,
407    KS: Serializer<Target = K>,
408    VS: Serializer<Target = V>,
409    I: Iterator<Item = (&'a K, &'a V)>,
410{
411    write_map_data_body!(value, K, V, KS, VS, iter, len, context, false)
412}
413
414fn write_field_map_data<'a, K, V, KC, VC, I>(
415    iter: I,
416    len: usize,
417    context: &mut WriteContext,
418    has_generics: bool,
419) -> Result<(), Error>
420where
421    K: 'static + 'a,
422    V: 'static + 'a,
423    KC: Codec<K>,
424    VC: Codec<V>,
425    I: Iterator<Item = (&'a K, &'a V)>,
426{
427    write_map_data_body!(field, K, V, KC, VC, iter, len, context, has_generics)
428}
429
430enum EntryReadType<'a> {
431    Direct,
432    Field(Cow<'a, FieldType>),
433    TypeInfo(Rc<TypeInfo>),
434}
435
436#[inline(always)]
437fn read_value_entry_type<T, S>(
438    context: &mut ReadContext,
439    declared: bool,
440) -> Result<Option<Rc<TypeInfo>>, Error>
441where
442    T: 'static,
443    S: Serializer<Target = T>,
444{
445    if declared {
446        return Ok(None);
447    }
448    read_value_type_info::<S>(context)
449}
450
451#[inline(always)]
452fn read_value_entry<T, S>(
453    context: &mut ReadContext,
454    read_type: &Option<Rc<TypeInfo>>,
455    track_ref: bool,
456) -> Result<T, Error>
457where
458    T: 'static,
459    S: Serializer<Target = T>,
460{
461    let ref_mode = if track_ref {
462        RefMode::Tracking
463    } else {
464        RefMode::None
465    };
466    match read_type {
467        None => S::read(context, ref_mode, false),
468        Some(type_info) => S::read_with_type_info(context, ref_mode, type_info),
469    }
470}
471
472#[inline(always)]
473fn read_entry_type<'a, T: 'static, C: Codec<T>>(
474    context: &mut ReadContext,
475    declared: bool,
476    remote_field_type: Option<&'a FieldType>,
477    index: usize,
478    track_ref: bool,
479) -> Result<EntryReadType<'a>, Error> {
480    if declared {
481        return match remote_field_type {
482            Some(field_type) => {
483                let field_type = generic_field_type(field_type, index, "map")?;
484                Ok(EntryReadType::Field(field_type_with_ref_flags(
485                    field_type,
486                    field_type.nullable,
487                    track_ref,
488                )))
489            }
490            None => Ok(EntryReadType::Direct),
491        };
492    }
493    match C::read_type_info_value(context)? {
494        CodecReadType::Field(mut field_type) => {
495            field_type.track_ref = track_ref;
496            Ok(EntryReadType::Field(Cow::Owned(field_type)))
497        }
498        CodecReadType::TypeInfo(type_info) => Ok(EntryReadType::TypeInfo(type_info)),
499    }
500}
501
502#[inline(always)]
503fn read_entry<T: 'static, C: Codec<T>>(
504    context: &mut ReadContext,
505    read_type: &EntryReadType<'_>,
506    track_ref: bool,
507) -> Result<T, Error> {
508    let ref_mode = if track_ref {
509        RefMode::Tracking
510    } else {
511        RefMode::None
512    };
513    match read_type {
514        EntryReadType::Direct => C::read(context, ref_mode, false),
515        EntryReadType::TypeInfo(type_info) => C::read_with_type_info(context, ref_mode, type_info),
516        EntryReadType::Field(field_type) if track_ref => {
517            C::read_field_with_type(context, field_type)
518        }
519        EntryReadType::Field(field_type) => C::read_data_with_type(context, field_type),
520    }
521}
522
523macro_rules! map_read_mode {
524    (value, $T:ty, $S:ty, $context:expr, $ref_mode:expr, $read_type:expr) => {
525        <$S as Serializer>::read($context, $ref_mode, $read_type)
526    };
527    (field, $T:ty, $C:ty, $context:expr, $ref_mode:expr, $read_type:expr) => {
528        <$C as Serializer>::read($context, $ref_mode, $read_type)
529    };
530}
531
532macro_rules! map_read_entry_type {
533    (value, $T:ty, $S:ty, $context:expr, $declared:expr, $remote:expr, $index:expr, $tracked:expr) => {
534        read_value_entry_type::<$T, $S>($context, $declared)
535    };
536    (field, $T:ty, $C:ty, $context:expr, $declared:expr, $remote:expr, $index:expr, $tracked:expr) => {
537        read_entry_type::<$T, $C>($context, $declared, $remote, $index, $tracked)
538    };
539}
540
541macro_rules! map_read_entry {
542    (value, $T:ty, $S:ty, $context:expr, $read_type:expr, $tracked:expr) => {
543        read_value_entry::<$T, $S>($context, $read_type, $tracked)
544    };
545    (field, $T:ty, $C:ty, $context:expr, $read_type:expr, $tracked:expr) => {
546        read_entry::<$T, $C>($context, $read_type, $tracked)
547    };
548}
549
550#[cold]
551#[inline(never)]
552fn invalid_map_chunk() -> Error {
553    Error::invalid_data("map chunk size must be within the remaining entry count")
554}
555
556#[cold]
557#[inline(never)]
558fn map_memory_overflow() -> Error {
559    Error::invalid_data("graph memory estimate overflows")
560}
561
562#[cold]
563#[inline(never)]
564fn map_type_mismatch(remote: u32) -> Error {
565    Error::type_mismatch(TypeId::MAP as u32, remote)
566}
567
568macro_rules! read_map_data_body {
569    (
570        $layer:ident,
571        $M:ident,
572        $K:ident,
573        $V:ident,
574        $KC:ident,
575        $VC:ident,
576        $context:expr,
577        $remote_field_type:expr
578    ) => {{
579        let context = $context;
580        let len = context.reader.read_var_u32()?;
581        let capacity = len as usize;
582        context.reader.check_bound(capacity)?;
583        let elem_bytes = std::mem::size_of::<$K>()
584            .checked_add(std::mem::size_of::<$V>())
585            .and_then(|bytes| bytes.checked_mul(capacity))
586            .ok_or_else(map_memory_overflow)?;
587        context.reserve_graph_memory(elem_bytes)?;
588        let mut map = $M::with_capacity(capacity);
589        let mut read = 0u32;
590        while read < len {
591            let header = context.reader.read_u8()?;
592            if header & KEY_NULL != 0 && header & VALUE_NULL != 0 {
593                map.insert($KC::default_value(context)?, $VC::default_value(context)?);
594                read += 1;
595                continue;
596            }
597            let key_declared = header & DECL_KEY_TYPE != 0;
598            let value_declared = header & DECL_VALUE_TYPE != 0;
599            let key_tracked = header & TRACKING_KEY_REF != 0;
600            let value_tracked = header & TRACKING_VALUE_REF != 0;
601            if header & KEY_NULL != 0 {
602                let value = if value_tracked && !value_declared {
603                    map_read_mode!($layer, $V, $VC, context, RefMode::Tracking, true)?
604                } else {
605                    let value_type = map_read_entry_type!(
606                        $layer,
607                        $V,
608                        $VC,
609                        context,
610                        value_declared,
611                        $remote_field_type,
612                        1,
613                        value_tracked
614                    )?;
615                    map_read_entry!($layer, $V, $VC, context, &value_type, value_tracked)?
616                };
617                map.insert($KC::default_value(context)?, value);
618                read += 1;
619                continue;
620            }
621            if header & VALUE_NULL != 0 {
622                let key = if key_tracked && !key_declared {
623                    map_read_mode!($layer, $K, $KC, context, RefMode::Tracking, true)?
624                } else {
625                    let key_type = map_read_entry_type!(
626                        $layer,
627                        $K,
628                        $KC,
629                        context,
630                        key_declared,
631                        $remote_field_type,
632                        0,
633                        key_tracked
634                    )?;
635                    map_read_entry!($layer, $K, $KC, context, &key_type, key_tracked)?
636                };
637                map.insert(key, $VC::default_value(context)?);
638                read += 1;
639                continue;
640            }
641            let chunk_size = context.reader.read_u8()? as u32;
642            if chunk_size == 0 {
643                return Err(invalid_map_chunk());
644            }
645            let end = read
646                .checked_add(chunk_size)
647                .filter(|end| *end <= len)
648                .ok_or_else(invalid_map_chunk)?;
649            let key_type = map_read_entry_type!(
650                $layer,
651                $K,
652                $KC,
653                context,
654                key_declared,
655                $remote_field_type,
656                0,
657                key_tracked
658            )?;
659            let value_type = map_read_entry_type!(
660                $layer,
661                $V,
662                $VC,
663                context,
664                value_declared,
665                $remote_field_type,
666                1,
667                value_tracked
668            )?;
669            while read < end {
670                let key = map_read_entry!($layer, $K, $KC, context, &key_type, key_tracked)?;
671                let value = map_read_entry!($layer, $V, $VC, context, &value_type, value_tracked)?;
672                map.insert(key, value);
673                read += 1;
674            }
675        }
676        Ok(map)
677    }};
678}
679
680fn read_value_map_data<M, K, V, KS, VS>(context: &mut ReadContext) -> Result<M, Error>
681where
682    K: 'static,
683    V: 'static,
684    KS: Serializer<Target = K>,
685    VS: Serializer<Target = V>,
686    M: MapTarget<K, V>,
687{
688    read_map_data_body!(value, M, K, V, KS, VS, context, ())
689}
690
691fn read_field_map_data<M, K, V, KC, VC>(
692    context: &mut ReadContext,
693    remote_field_type: Option<&FieldType>,
694) -> Result<M, Error>
695where
696    K: 'static,
697    V: 'static,
698    KC: Codec<K>,
699    VC: Codec<V>,
700    M: MapTarget<K, V>,
701{
702    read_map_data_body!(field, M, K, V, KC, VC, context, remote_field_type)
703}
704
705macro_rules! impl_map_codec {
706    ($codec:ident, $target:ident, [$($key_bound:tt)+]) => {
707        impl<K, V, KS, VS, const NULLABLE: bool, const TRACK_REF: bool> Serializer
708            for $codec<K, V, KS, VS, NULLABLE, TRACK_REF>
709        where
710            K: $($key_bound)+ + 'static,
711            V: 'static,
712            KS: Serializer<Target = K>,
713            VS: Serializer<Target = V>,
714        {
715            type Target = $target<K, V>;
716
717            #[inline(always)]
718            fn write_data(
719                value: &Self::Target,
720                context: &mut WriteContext,
721            ) -> Result<(), Error> {
722                write_value_map_data::<K, V, KS, VS, _>(
723                    value.iter(),
724                    value.len(),
725                    context,
726                )
727            }
728
729            #[inline(always)]
730            fn read_data(context: &mut ReadContext) -> Result<Self::Target, Error> {
731                read_value_map_data::<Self::Target, K, V, KS, VS>(context)
732            }
733
734            #[inline(always)]
735            fn default_value(_: &mut ReadContext) -> Result<Self::Target, Error> {
736                Ok(<Self::Target as MapTarget<K, V>>::with_capacity(0))
737            }
738
739            #[inline(always)]
740            fn write_type_info(context: &mut WriteContext) -> Result<(), Error> {
741                context.writer.write_u8(TypeId::MAP as u8);
742                Ok(())
743            }
744
745            #[inline(always)]
746            fn read_type_info(context: &mut ReadContext) -> Result<(), Error> {
747                let remote = context.reader.read_u8()? as u32;
748                if remote == TypeId::MAP as u32 {
749                    Ok(())
750                } else {
751                    Err(map_type_mismatch(remote))
752                }
753            }
754
755            #[inline(always)]
756            fn static_type_id() -> TypeId {
757                TypeId::MAP
758            }
759
760            #[inline(always)]
761            fn reserved_space() -> usize {
762                std::mem::size_of::<u32>() + SIZE_OF_REF_AND_TYPE
763            }
764        }
765
766        impl<K, V, KC, VC, const NULLABLE: bool, const TRACK_REF: bool>
767            Codec<$target<K, V>> for $codec<K, V, KC, VC, NULLABLE, TRACK_REF>
768        where
769            K: $($key_bound)+ + 'static,
770            V: 'static,
771            KC: Codec<K>,
772            VC: Codec<V>,
773        {
774            #[inline(always)]
775            fn field_type(type_resolver: &TypeResolver) -> Result<FieldType, Error> {
776                Ok(FieldType::new_with_ref(
777                    TypeId::MAP as u32,
778                    NULLABLE,
779                    TRACK_REF,
780                    vec![
781                        KC::field_type(type_resolver)?,
782                        VC::field_type(type_resolver)?,
783                    ],
784                ))
785            }
786
787            #[inline(always)]
788            fn write_field(
789                value: &$target<K, V>,
790                context: &mut WriteContext,
791            ) -> Result<(), Error> {
792                if NULLABLE || TRACK_REF {
793                    context.writer.write_i8(RefFlag::NotNullValue as i8);
794                }
795                write_field_map_data::<K, V, KC, VC, _>(
796                    value.iter(),
797                    value.len(),
798                    context,
799                    true,
800                )
801            }
802
803            #[inline(always)]
804            fn read_field(context: &mut ReadContext) -> Result<$target<K, V>, Error> {
805                if (NULLABLE || TRACK_REF)
806                    && context.reader.read_i8()? == RefFlag::Null as i8
807                {
808                    return Ok(
809                        <$target<K, V> as MapTarget<K, V>>::with_capacity(0)
810                    );
811                }
812                <Self as Serializer>::read_data(context)
813            }
814
815            #[inline(always)]
816            fn read_data_with_type(
817                context: &mut ReadContext,
818                remote_data_type: &FieldType,
819            ) -> Result<$target<K, V>, Error> {
820                read_field_map_data::<$target<K, V>, K, V, KC, VC>(
821                    context,
822                    Some(remote_data_type),
823                )
824            }
825
826            #[inline(always)]
827            fn read_field_with_type(
828                context: &mut ReadContext,
829                remote_field_type: &FieldType,
830            ) -> Result<$target<K, V>, Error> {
831                if field_ref_mode(remote_field_type) != RefMode::None
832                    && context.reader.read_i8()? == RefFlag::Null as i8
833                {
834                    return Ok(
835                        <$target<K, V> as MapTarget<K, V>>::with_capacity(0)
836                    );
837                }
838                Self::read_data_with_type(context, remote_field_type)
839            }
840
841            #[inline(always)]
842            fn write_with_mode(
843                value: &$target<K, V>,
844                context: &mut WriteContext,
845                ref_mode: RefMode,
846                write_type_info: bool,
847                has_generics: bool,
848            ) -> Result<(), Error> {
849                if !has_generics {
850                    return <Self as Serializer>::write(
851                        value,
852                        context,
853                        ref_mode,
854                        write_type_info,
855                    );
856                }
857                if ref_mode != RefMode::None {
858                    context.writer.write_i8(RefFlag::NotNullValue as i8);
859                }
860                if write_type_info {
861                    <Self as Serializer>::write_type_info(context)?;
862                }
863                write_field_map_data::<K, V, KC, VC, _>(
864                    value.iter(),
865                    value.len(),
866                    context,
867                    true,
868                )
869            }
870        }
871    };
872}
873
874impl_map_codec!(HashMapCodec, HashMap, [Eq + std::hash::Hash]);
875impl_map_codec!(BTreeMapCodec, BTreeMap, [Ord]);
876
877macro_rules! impl_map_serializer {
878    ($provider:ident, $target:ident, $codec:ident, [$($key_bound:tt)+]) => {
879        #[doc = concat!(
880            "Statically serializes `",
881            stringify!($target),
882            "<KS::Target, VS::Target>` at roots or recursive carrier nodes. ",
883            "This zero-sized carrier composes its key and value serializers and is not ",
884            "registered independently."
885        )]
886        pub struct $provider<KS, VS>(PhantomData<fn() -> (KS, VS)>);
887
888        impl<KS, VS> Serializer for $provider<KS, VS>
889        where
890            KS: Serializer,
891            VS: Serializer,
892            KS::Target: $($key_bound)+,
893        {
894            type Target = $target<KS::Target, VS::Target>;
895
896            #[inline(always)]
897            fn write_data(value: &Self::Target, context: &mut WriteContext) -> Result<(), Error> {
898                <$codec<
899                    KS::Target,
900                    VS::Target,
901                    KS,
902                    VS,
903                    false,
904                    false,
905                > as Serializer>::write_data(value, context)
906            }
907
908            #[inline(always)]
909            fn read_data(context: &mut ReadContext) -> Result<Self::Target, Error> {
910                <$codec<
911                    KS::Target,
912                    VS::Target,
913                    KS,
914                    VS,
915                    false,
916                    false,
917                > as Serializer>::read_data(context)
918            }
919
920            #[inline(always)]
921            fn default_value(context: &mut ReadContext) -> Result<Self::Target, Error> {
922                <$codec<
923                    KS::Target,
924                    VS::Target,
925                    KS,
926                    VS,
927                    false,
928                    false,
929                > as Serializer>::default_value(context)
930            }
931
932            #[inline(always)]
933            fn write(
934                value: &Self::Target,
935                context: &mut WriteContext,
936                ref_mode: RefMode,
937                write_type_info: bool,
938            ) -> Result<(), Error> {
939                <$codec<
940                    KS::Target,
941                    VS::Target,
942                    KS,
943                    VS,
944                    false,
945                    false,
946                > as Serializer>::write(
947                    value,
948                    context,
949                    ref_mode,
950                    write_type_info,
951                )
952            }
953
954            #[inline(always)]
955            fn read(
956                context: &mut ReadContext,
957                ref_mode: RefMode,
958                read_type_info: bool,
959            ) -> Result<Self::Target, Error> {
960                <$codec<
961                    KS::Target,
962                    VS::Target,
963                    KS,
964                    VS,
965                    false,
966                    false,
967                > as Serializer>::read(
968                    context,
969                    ref_mode,
970                    read_type_info,
971                )
972            }
973
974            #[inline(always)]
975            fn read_with_type_info(
976                context: &mut ReadContext,
977                ref_mode: RefMode,
978                type_info: &Rc<TypeInfo>,
979            ) -> Result<Self::Target, Error> {
980                <$codec<
981                    KS::Target,
982                    VS::Target,
983                    KS,
984                    VS,
985                    false,
986                    false,
987                > as Serializer>::read_with_type_info(
988                    context,
989                    ref_mode,
990                    type_info,
991                )
992            }
993
994            #[inline(always)]
995            fn write_type_info(context: &mut WriteContext) -> Result<(), Error> {
996                <$codec<
997                    KS::Target,
998                    VS::Target,
999                    KS,
1000                    VS,
1001                    false,
1002                    false,
1003                > as Serializer>::write_type_info(context)
1004            }
1005
1006            #[inline(always)]
1007            fn read_type_info(context: &mut ReadContext) -> Result<(), Error> {
1008                <$codec<
1009                    KS::Target,
1010                    VS::Target,
1011                    KS,
1012                    VS,
1013                    false,
1014                    false,
1015                > as Serializer>::read_type_info(context)
1016            }
1017
1018            #[inline(always)]
1019            fn static_type_id() -> TypeId {
1020                TypeId::MAP
1021            }
1022
1023            #[inline(always)]
1024            fn reserved_space() -> usize {
1025                std::mem::size_of::<u32>() + SIZE_OF_REF_AND_TYPE
1026            }
1027        }
1028
1029        impl<K, V> Serializer for $target<K, V>
1030        where
1031            K: Serializer<Target = K> + $($key_bound)+,
1032            V: Serializer<Target = V>,
1033        {
1034            type Target = Self;
1035
1036            #[inline(always)]
1037            fn write_data(value: &Self, context: &mut WriteContext) -> Result<(), Error> {
1038                <$provider<K, V> as Serializer>::write_data(value, context)
1039            }
1040
1041            #[inline(always)]
1042            fn read_data(context: &mut ReadContext) -> Result<Self, Error> {
1043                <$provider<K, V> as Serializer>::read_data(context)
1044            }
1045
1046            #[inline(always)]
1047            fn default_value(context: &mut ReadContext) -> Result<Self, Error> {
1048                <$provider<K, V> as Serializer>::default_value(context)
1049            }
1050
1051            #[inline(always)]
1052            fn write(
1053                value: &Self,
1054                context: &mut WriteContext,
1055                ref_mode: RefMode,
1056                write_type_info: bool,
1057            ) -> Result<(), Error> {
1058                <$provider<K, V> as Serializer>::write(
1059                    value,
1060                    context,
1061                    ref_mode,
1062                    write_type_info,
1063                )
1064            }
1065
1066            #[inline(always)]
1067            fn read(
1068                context: &mut ReadContext,
1069                ref_mode: RefMode,
1070                read_type_info: bool,
1071            ) -> Result<Self, Error> {
1072                <$provider<K, V> as Serializer>::read(
1073                    context,
1074                    ref_mode,
1075                    read_type_info,
1076                )
1077            }
1078
1079            #[inline(always)]
1080            fn read_with_type_info(
1081                context: &mut ReadContext,
1082                ref_mode: RefMode,
1083                type_info: &Rc<TypeInfo>,
1084            ) -> Result<Self, Error> {
1085                <$provider<K, V> as Serializer>::read_with_type_info(
1086                    context,
1087                    ref_mode,
1088                    type_info,
1089                )
1090            }
1091
1092            #[inline(always)]
1093            fn write_type_info(context: &mut WriteContext) -> Result<(), Error> {
1094                <$provider<K, V> as Serializer>::write_type_info(context)
1095            }
1096
1097            #[inline(always)]
1098            fn read_type_info(context: &mut ReadContext) -> Result<(), Error> {
1099                <$provider<K, V> as Serializer>::read_type_info(context)
1100            }
1101
1102            #[inline(always)]
1103            fn static_type_id() -> TypeId {
1104                TypeId::MAP
1105            }
1106
1107            #[inline(always)]
1108            fn reserved_space() -> usize {
1109                std::mem::size_of::<u32>() + SIZE_OF_REF_AND_TYPE
1110            }
1111        }
1112    };
1113}
1114
1115impl_map_serializer!(
1116    HashMapSerializer,
1117    HashMap,
1118    HashMapCodec,
1119    [Eq + std::hash::Hash]
1120);
1121impl_map_serializer!(BTreeMapSerializer, BTreeMap, BTreeMapCodec, [Ord]);