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