1#![deny(missing_docs)]
2
3use std::io::{Read, Write};
26
27use tls_codec::{Deserialize, Serialize, Size};
28
29#[derive(Debug, thiserror::Error)]
31pub enum TlsMapError {
32 #[error("key already exists")]
34 KeyExists,
35 #[error("key not found")]
37 KeyNotFound,
38 #[error("tls codec error: {0}")]
40 Codec(#[from] tls_codec::Error),
41}
42
43#[derive(Clone, PartialEq, Eq)]
47pub struct TlsMapEntry<K, V> {
48 pub key: K,
50 pub value: V,
52}
53
54impl<K: std::fmt::Debug, V: std::fmt::Debug> std::fmt::Debug for TlsMapEntry<K, V> {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 write!(f, "{{ key: {:?}, value: {:?} }}", self.key, self.value)
57 }
58}
59
60impl<K: Size, V: Size> Size for TlsMapEntry<K, V> {
61 #[inline]
62 fn tls_serialized_len(&self) -> usize {
63 self.key.tls_serialized_len() + self.value.tls_serialized_len()
64 }
65}
66
67impl<K: Serialize, V: Serialize> Serialize for TlsMapEntry<K, V> {
68 #[inline]
69 fn tls_serialize<W: Write>(&self, writer: &mut W) -> Result<usize, tls_codec::Error> {
70 let key_size = self.key.tls_serialize(writer)?;
71 let value_size = self.value.tls_serialize(writer)?;
72 Ok(key_size + value_size)
73 }
74}
75
76impl<K: Deserialize + Size, V: Deserialize + Size> Deserialize for TlsMapEntry<K, V> {
77 #[inline]
78 fn tls_deserialize<R: Read>(bytes: &mut R) -> Result<Self, tls_codec::Error>
79 where
80 Self: Sized,
81 {
82 let key = K::tls_deserialize(bytes)?;
83 let value = V::tls_deserialize(bytes)?;
84 Ok(Self { key, value })
85 }
86}
87
88#[derive(Debug, Clone, PartialEq, Eq)]
114pub struct TlsMap<K, V> {
115 entries: Vec<TlsMapEntry<K, V>>,
116}
117
118impl<K, V> Default for TlsMap<K, V> {
119 #[inline]
120 fn default() -> Self {
121 Self {
122 entries: Vec::new(),
123 }
124 }
125}
126
127impl<K, V> TlsMap<K, V>
128where
129 K: Ord + Eq,
130{
131 #[inline]
140 pub fn new() -> Self {
141 Self::default()
142 }
143
144 pub fn from_pairs(iter: impl IntoIterator<Item = (K, V)>) -> Self {
157 let entries = iter
158 .into_iter()
159 .collect::<std::collections::BTreeMap<K, V>>()
160 .into_iter()
161 .map(|(key, value)| TlsMapEntry { key, value })
162 .collect();
163 Self { entries }
164 }
165
166 #[inline]
176 pub fn insert(&mut self, key: K, value: V) -> Result<(), TlsMapError> {
177 match self.entries.binary_search_by(|e| e.key.cmp(&key)) {
178 Ok(_) => Err(TlsMapError::KeyExists),
179 Err(idx) => {
180 self.entries.insert(idx, TlsMapEntry { key, value });
181 Ok(())
182 }
183 }
184 }
185
186 #[inline]
198 pub fn update(&mut self, key: K, value: V) -> Result<(), TlsMapError> {
199 match self.entries.binary_search_by(|e| e.key.cmp(&key)) {
200 Ok(idx) => {
201 self.entries[idx].value = value;
202 Ok(())
203 }
204 Err(_) => Err(TlsMapError::KeyNotFound),
205 }
206 }
207
208 #[inline]
220 pub fn set(&mut self, key: K, value: V) {
221 match self.entries.binary_search_by(|e| e.key.cmp(&key)) {
222 Ok(idx) => self.entries[idx].value = value,
223 Err(idx) => self.entries.insert(idx, TlsMapEntry { key, value }),
224 }
225 }
226
227 #[inline]
238 pub fn remove(&mut self, key: &K) -> Result<V, TlsMapError> {
239 match self.entries.binary_search_by(|e| e.key.cmp(key)) {
240 Ok(idx) => Ok(self.entries.remove(idx).value),
241 Err(_) => Err(TlsMapError::KeyNotFound),
242 }
243 }
244
245 #[inline]
256 pub fn get(&self, key: &K) -> Option<&V> {
257 self.entries
258 .binary_search_by(|e| e.key.cmp(key))
259 .ok()
260 .map(|idx| &self.entries[idx].value)
261 }
262
263 #[inline]
274 pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
275 self.entries
276 .binary_search_by(|e| e.key.cmp(key))
277 .ok()
278 .map(|idx| &mut self.entries[idx].value)
279 }
280
281 #[inline]
283 pub fn contains_key(&self, key: &K) -> bool {
284 self.entries.binary_search_by(|e| e.key.cmp(key)).is_ok()
285 }
286
287 #[inline]
289 pub fn len(&self) -> usize {
290 self.entries.len()
291 }
292
293 #[inline]
295 pub fn is_empty(&self) -> bool {
296 self.entries.is_empty()
297 }
298
299 #[inline]
309 pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
310 self.entries.iter().map(|e| (&e.key, &e.value))
311 }
312
313 #[inline]
315 pub fn keys(&self) -> impl Iterator<Item = &K> {
316 self.entries.iter().map(|e| &e.key)
317 }
318
319 #[inline]
321 pub fn values(&self) -> impl Iterator<Item = &V> {
322 self.entries.iter().map(|e| &e.value)
323 }
324}
325
326impl<K: Size, V: Size> Size for TlsMap<K, V> {
331 #[inline]
332 fn tls_serialized_len(&self) -> usize {
333 self.entries.tls_serialized_len()
334 }
335}
336
337impl<K: Serialize + Size + std::fmt::Debug, V: Serialize + Size + std::fmt::Debug> Serialize
338 for TlsMap<K, V>
339{
340 #[inline]
341 fn tls_serialize<W: Write>(&self, writer: &mut W) -> Result<usize, tls_codec::Error> {
342 self.entries.tls_serialize(writer)
343 }
344}
345
346impl<K, V> Deserialize for TlsMap<K, V>
347where
348 K: Deserialize + Size + Ord + Eq,
349 V: Deserialize + Size,
350{
351 fn tls_deserialize<R: Read>(bytes: &mut R) -> Result<Self, tls_codec::Error>
352 where
353 Self: Sized,
354 {
355 let entries = Vec::<TlsMapEntry<K, V>>::tls_deserialize(bytes)?;
356
357 for [l, r] in entries.array_windows::<2>() {
359 if l.key >= r.key {
360 return Err(tls_codec::Error::DecodingError(
361 "TlsMap entries not sorted or contain duplicates".into(),
362 ));
363 }
364 }
365
366 Ok(Self { entries })
367 }
368}
369
370enum UndoAction<K, V> {
374 Remove(K),
376 Restore(K, V),
378 Insert(K, V),
380}
381
382#[derive(Debug, Clone, PartialEq, Eq)]
386pub enum TlsMapMutation<K, V> {
387 Insert {
389 key: K,
391 value: V,
393 },
394 Update {
396 key: K,
398 value: V,
400 },
401 Delete {
403 key: K,
405 },
406}
407
408#[derive(Debug, Clone, PartialEq, Eq)]
422pub struct TlsMapDelta<K, V> {
423 pub mutations: Vec<TlsMapMutation<K, V>>,
425}
426
427impl<K, V> TlsMapDelta<K, V> {
428 #[inline]
430 pub fn new() -> Self {
431 Self {
432 mutations: Vec::new(),
433 }
434 }
435
436 #[inline]
438 pub fn insert(mut self, key: K, value: V) -> Self {
439 self.mutations.push(TlsMapMutation::Insert { key, value });
440 self
441 }
442
443 #[inline]
445 pub fn update(mut self, key: K, value: V) -> Self {
446 self.mutations.push(TlsMapMutation::Update { key, value });
447 self
448 }
449
450 #[inline]
452 pub fn delete(mut self, key: K) -> Self {
453 self.mutations.push(TlsMapMutation::Delete { key });
454 self
455 }
456}
457
458impl<K, V> Default for TlsMapDelta<K, V> {
459 #[inline]
460 fn default() -> Self {
461 Self::new()
462 }
463}
464
465impl<K, V> TlsMap<K, V>
466where
467 K: Ord + Eq + Clone,
468{
469 pub fn apply_delta(&mut self, delta: TlsMapDelta<K, V>) -> Result<(), TlsMapError> {
487 let mut undo_stack: Vec<UndoAction<K, V>> = Vec::with_capacity(delta.mutations.len());
488
489 for mutation in delta.mutations {
490 match mutation {
491 TlsMapMutation::Insert { key, value } => {
492 if let Err(e) = self.insert(key.clone(), value) {
493 self.rollback(undo_stack);
494 return Err(e);
495 }
496 undo_stack.push(UndoAction::Remove(key));
497 }
498 TlsMapMutation::Update { key, mut value } => match self.get_mut(&key) {
499 Some(old) => {
500 std::mem::swap(old, &mut value);
501 undo_stack.push(UndoAction::Restore(key, value));
502 }
503 None => {
504 self.rollback(undo_stack);
505 return Err(TlsMapError::KeyNotFound);
506 }
507 },
508 TlsMapMutation::Delete { key } => match self.remove(&key) {
509 Ok(old) => {
510 undo_stack.push(UndoAction::Insert(key, old));
511 }
512 Err(e) => {
513 self.rollback(undo_stack);
514 return Err(e);
515 }
516 },
517 }
518 }
519
520 Ok(())
521 }
522
523 fn rollback(&mut self, undo_stack: Vec<UndoAction<K, V>>) {
525 for action in undo_stack.into_iter().rev() {
526 match action {
527 UndoAction::Remove(key) => {
528 let _ = self.remove(&key);
530 }
531 UndoAction::Restore(key, value) | UndoAction::Insert(key, value) => {
532 self.set(key, value);
533 }
534 }
535 }
536 }
537}
538
539impl<K: Size, V: Size> Size for TlsMapMutation<K, V> {
543 fn tls_serialized_len(&self) -> usize {
544 1 + match self {
545 Self::Insert { key, value } | Self::Update { key, value } => {
546 key.tls_serialized_len() + value.tls_serialized_len()
547 }
548 Self::Delete { key } => key.tls_serialized_len(),
549 }
550 }
551}
552
553impl<K: Serialize + Size, V: Serialize + Size> Serialize for TlsMapMutation<K, V> {
554 fn tls_serialize<W: Write>(&self, writer: &mut W) -> Result<usize, tls_codec::Error> {
555 match self {
556 Self::Insert { key, value } => {
557 let mut written = 0u8.tls_serialize(writer)?;
558 written += key.tls_serialize(writer)?;
559 written += value.tls_serialize(writer)?;
560 Ok(written)
561 }
562 Self::Update { key, value } => {
563 let mut written = 1u8.tls_serialize(writer)?;
564 written += key.tls_serialize(writer)?;
565 written += value.tls_serialize(writer)?;
566 Ok(written)
567 }
568 Self::Delete { key } => {
569 let mut written = 2u8.tls_serialize(writer)?;
570 written += key.tls_serialize(writer)?;
571 Ok(written)
572 }
573 }
574 }
575}
576
577impl<K, V> Deserialize for TlsMapMutation<K, V>
578where
579 K: Deserialize + Size,
580 V: Deserialize + Size,
581{
582 fn tls_deserialize<R: Read>(bytes: &mut R) -> Result<Self, tls_codec::Error>
583 where
584 Self: Sized,
585 {
586 let tag = u8::tls_deserialize(bytes)?;
587 match tag {
588 0 => {
589 let key = K::tls_deserialize(bytes)?;
590 let value = V::tls_deserialize(bytes)?;
591 Ok(Self::Insert { key, value })
592 }
593 1 => {
594 let key = K::tls_deserialize(bytes)?;
595 let value = V::tls_deserialize(bytes)?;
596 Ok(Self::Update { key, value })
597 }
598 2 => {
599 let key = K::tls_deserialize(bytes)?;
600 Ok(Self::Delete { key })
601 }
602 _ => Err(tls_codec::Error::DecodingError(format!(
603 "unknown TlsMapMutation tag: {tag}"
604 ))),
605 }
606 }
607}
608
609impl<K: Size, V: Size> Size for TlsMapDelta<K, V> {
610 #[inline]
611 fn tls_serialized_len(&self) -> usize {
612 self.mutations.tls_serialized_len()
613 }
614}
615
616impl<K: Serialize + Size + std::fmt::Debug, V: Serialize + Size + std::fmt::Debug> Serialize
617 for TlsMapDelta<K, V>
618{
619 #[inline]
620 fn tls_serialize<W: Write>(&self, writer: &mut W) -> Result<usize, tls_codec::Error> {
621 self.mutations.tls_serialize(writer)
622 }
623}
624
625impl<K, V> Deserialize for TlsMapDelta<K, V>
626where
627 K: Deserialize + Size,
628 V: Deserialize + Size,
629{
630 fn tls_deserialize<R: Read>(bytes: &mut R) -> Result<Self, tls_codec::Error>
631 where
632 Self: Sized,
633 {
634 let mutations = Vec::<TlsMapMutation<K, V>>::tls_deserialize(bytes)?;
635 Ok(Self { mutations })
636 }
637}
638
639impl<K, V> IntoIterator for TlsMap<K, V> {
642 type Item = (K, V);
643 type IntoIter =
644 std::iter::Map<std::vec::IntoIter<TlsMapEntry<K, V>>, fn(TlsMapEntry<K, V>) -> (K, V)>;
645
646 #[inline]
647 fn into_iter(self) -> Self::IntoIter {
648 self.entries.into_iter().map(|e| (e.key, e.value))
649 }
650}
651
652impl<K: Ord + Eq, V> FromIterator<(K, V)> for TlsMap<K, V> {
653 #[inline]
654 fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
655 Self::from_pairs(iter)
656 }
657}
658
659#[cfg(test)]
660mod tests {
661 use super::*;
662 use proptest::prelude::*;
663
664 fn build_map<K: Ord + Eq, V>(pairs: impl Iterator<Item = (K, V)>) -> TlsMap<K, V> {
668 pairs.collect()
669 }
670
671 macro_rules! tls_map_tests {
675 ($mod_name:ident, $K:ty, $V:ty, $n:expr, $mutate_v:expr) => {
676 mod $mod_name {
677 use super::*;
678
679 proptest! {
680 #[test]
681 fn round_trip(
682 pairs in proptest::collection::vec((any::<$K>(), any::<$V>()), 0..$n)
683 ) {
684 let map = build_map(pairs.into_iter());
685 let bytes = map.tls_serialize_detached().expect("round trip serialization should succeed");
686 let deserialized =
687 TlsMap::<$K, $V>::tls_deserialize_exact(&bytes).expect("round trip deserialization should succeed");
688 prop_assert_eq!(map, deserialized);
689 }
690
691 #[test]
692 fn deterministic(
693 pairs in proptest::collection::vec((any::<$K>(), any::<$V>()), 0..$n)
694 ) {
695 let map = build_map(pairs.into_iter());
696 let a = map.tls_serialize_detached().unwrap();
697 let b = map.tls_serialize_detached().unwrap();
698 prop_assert_eq!(a, b);
699 }
700
701 #[test]
702 fn insertion_order_irrelevant(
703 pairs in proptest::collection::hash_map(
704 any::<$K>(), any::<$V>(), 2..$n
705 )
706 ) {
707 let map_a = build_map(pairs.into_iter());
708 let map_b = build_map(map_a.clone().into_iter().rev());
709 prop_assert_eq!(
710 map_a.tls_serialize_detached().unwrap(),
711 map_b.tls_serialize_detached().unwrap()
712 );
713 }
714
715 #[test]
716 fn keys_always_sorted(
717 pairs in proptest::collection::vec((any::<$K>(), any::<$V>()), 0..$n)
718 ) {
719 let map = build_map(pairs.into_iter());
720 let keys: Vec<&$K> = map.keys().collect();
721 for w in keys.array_windows::<2>() {
722 prop_assert!(w[0] < w[1]);
723 }
724 }
725
726 #[test]
727 fn get_returns_inserted(
728 pairs in proptest::collection::vec((any::<$K>(), any::<$V>()), 1..$n)
729 ) {
730 let map = build_map(pairs.clone().into_iter());
731 let expected: std::collections::HashMap<$K, $V> = pairs
732 .into_iter()
733 .collect();
734 prop_assert_eq!(map.len(), expected.len());
735 for (k, v) in &expected {
736 prop_assert_eq!(map.get(k), Some(v));
737 }
738 }
739
740 #[test]
741 fn insert_duplicate_fails(pairs in proptest::collection::vec((any::<$K>(), any::<$V>()), 1..$n)) {
742 let mut map = build_map(pairs.clone().into_iter());
743 for (k, v) in pairs {
744 let v2 = ($mutate_v)(v);
745 prop_assert!(matches!(
746 map.insert(k, v2),
747 Err(TlsMapError::KeyExists)
748 ));
749 }
750 }
751
752 #[test]
753 fn set_upsert(pairs in proptest::collection::vec((any::<$K>(), any::<$V>()), 1..$n)) {
754 let mut map = TlsMap::new();
755 let mut key_set = std::collections::BTreeSet::new();
756 for (k, v) in pairs {
757 key_set.insert(k.clone());
758 map.set(k.clone(), v.clone());
759 prop_assert_eq!(map.get(&k), Some(&v));
760 let v2 = ($mutate_v)(v);
761 map.set(k.clone(), v2.clone());
762 prop_assert_eq!(map.get(&k), Some(&v2));
763 prop_assert_eq!(map.len(), key_set.len());
764 }
765 }
766
767 #[test]
768 fn remove_returns_value(pairs in proptest::collection::hash_map(any::<$K>(), any::<$V>(), 2..$n)) {
769 let mut map = build_map(pairs.clone().into_iter());
770 for (k, v) in pairs {
771 prop_assert_eq!(map.remove(&k).unwrap(), v);
772 }
773 prop_assert!(map.is_empty());
774 }
775
776 #[test]
777 fn serialized_size_matches_trait(
778 pairs in proptest::collection::vec((any::<$K>(), any::<$V>()), 0..$n)
779 ) {
780 let map = build_map(pairs.into_iter());
781 let bytes = map.tls_serialize_detached().unwrap();
782 prop_assert_eq!(bytes.len(), map.tls_serialized_len());
783 }
784
785 #[test]
786 fn from_pairs_and_collect_and_set_equivalent(
787 pairs in proptest::collection::vec((any::<$K>(), any::<$V>()), 0..$n)
788 ) {
789 let map_a = TlsMap::from_pairs(pairs.clone());
790 let map_b = pairs.clone().into_iter().collect::<TlsMap<$K, $V>>();
791 let mut map_c = TlsMap::new();
792 for (k, v) in pairs {
793 map_c.set(k, v);
794 }
795 prop_assert_eq!(
796 map_a.tls_serialize_detached().unwrap(),
797 map_b.tls_serialize_detached().unwrap()
798 );
799 prop_assert_eq!(
800 map_a.tls_serialize_detached().unwrap(),
801 map_c.tls_serialize_detached().unwrap()
802 );
803 }
804
805 #[test]
806 fn delta_rollback_on_failure(
807 pairs in proptest::collection::vec(
808 (any::<$K>(), any::<$V>()), 1..std::cmp::min($n, 200)
809 ),
810 bad_key: $K,
811 ) {
812 let mut map = build_map(pairs.into_iter());
813 let _ = map.remove(&bad_key);
814 let snapshot = map.clone();
815
816 let delta = TlsMapDelta::new().update(bad_key, <$V>::default());
817 prop_assert!(map.apply_delta(delta).is_err());
818 prop_assert_eq!(map, snapshot);
819 }
820
821 #[test]
822 fn into_iter_sorted(
823 pairs in proptest::collection::vec((any::<$K>(), any::<$V>()), 0..$n)
824 ) {
825 let map = build_map(pairs.into_iter());
826 let collected: Vec<($K, $V)> = map.into_iter().collect();
827 for w in collected.array_windows::<2>() {
828 prop_assert!(w[0].0 < w[1].0);
829 }
830 }
831
832 #[test]
834 fn single_entry_round_trip(key in any::<$K>(), value in any::<$V>()) {
835 let mut map = TlsMap::<$K, $V>::new();
836 map.insert(key, value).unwrap();
837 let bytes = map.tls_serialize_detached().unwrap();
838 prop_assert_eq!(bytes.len(), map.tls_serialized_len());
839 let deserialized = TlsMap::<$K, $V>::tls_deserialize_exact(&bytes).unwrap();
840 prop_assert_eq!(map, deserialized);
841 }
842
843 #[test]
845 fn rejects_unsorted(
846 a in any::<$K>(),
847 b in any::<$K>(),
848 va in any::<$V>(),
849 vb in any::<$V>(),
850 ) {
851 if a >= b { return Ok(()); }
852 let mut content = Vec::new();
854 b.tls_serialize(&mut content).unwrap();
855 va.tls_serialize(&mut content).unwrap();
856 a.tls_serialize(&mut content).unwrap();
857 vb.tls_serialize(&mut content).unwrap();
858
859 let mut bytes = Vec::new();
860 tls_codec::vlen::write_length(&mut bytes, content.len()).unwrap();
861 bytes.extend_from_slice(&content);
862
863 prop_assert!(TlsMap::<$K, $V>::tls_deserialize_exact(&bytes).is_err());
864 }
865
866 #[test]
868 fn rejects_duplicates(
869 key in any::<$K>(),
870 va in any::<$V>(),
871 vb in any::<$V>(),
872 ) {
873 let mut content = Vec::new();
874 key.tls_serialize(&mut content).unwrap();
875 va.tls_serialize(&mut content).unwrap();
876 key.tls_serialize(&mut content).unwrap();
877 vb.tls_serialize(&mut content).unwrap();
878
879 let mut bytes = Vec::new();
880 tls_codec::vlen::write_length(&mut bytes, content.len()).unwrap();
881 bytes.extend_from_slice(&content);
882
883 prop_assert!(TlsMap::<$K, $V>::tls_deserialize_exact(&bytes).is_err());
884 }
885
886 #[test]
888 fn mutation_round_trip(key in any::<$K>(), value in any::<$V>(), tag in 0u8..3) {
889 let mutation = match tag {
890 0 => TlsMapMutation::Insert { key, value },
891 1 => TlsMapMutation::Update { key, value },
892 _ => TlsMapMutation::Delete { key },
893 };
894 let bytes = mutation.tls_serialize_detached().unwrap();
895 let rt = TlsMapMutation::<$K, $V>::tls_deserialize_exact(&bytes).unwrap();
896 prop_assert_eq!(mutation, rt);
897 }
898
899 #[test]
901 fn delta_apply_sequence(
902 existing in proptest::collection::hash_map(
903 any::<$K>(), any::<$V>(), 2..std::cmp::min($n, 50)
904 ),
905 new_entries in proptest::collection::hash_map(
906 any::<$K>(), any::<$V>(), 1..std::cmp::min($n, 50)
907 ),
908 updated_value in any::<$V>(),
909 ) {
910 let new_entries: std::collections::HashMap<_, _> = new_entries
911 .into_iter()
912 .filter(|(k, _)| !existing.contains_key(k))
913 .collect();
914 if new_entries.is_empty() { return Ok(()); }
915
916 let existing_keys: Vec<_> = existing.keys().cloned().collect();
918 let mid = existing_keys.len() / 2;
919 let (update_only, update_and_delete) = existing_keys.split_at(mid);
920 if update_only.is_empty() || update_and_delete.is_empty() { return Ok(()); }
921
922 let mut map: TlsMap<$K, $V> = existing.iter()
923 .map(|(k, v)| (k.clone(), v.clone()))
924 .collect();
925
926 let mut delta = TlsMapDelta::new();
927 for (k, v) in &new_entries {
928 delta = delta.insert(k.clone(), v.clone());
929 }
930 for k in &existing_keys {
931 delta = delta.update(k.clone(), updated_value.clone());
932 }
933 for k in update_and_delete {
934 delta = delta.delete(k.clone());
935 }
936
937 map.apply_delta(delta).unwrap();
938 prop_assert_eq!(map.len(), new_entries.len() + update_only.len());
939 for (k, v) in &new_entries {
940 prop_assert_eq!(map.get(k), Some(v));
941 }
942 for k in update_only {
943 prop_assert_eq!(map.get(k), Some(&updated_value));
944 }
945 for k in update_and_delete {
946 prop_assert!(!map.contains_key(k));
947 }
948 }
949
950 #[test]
952 fn nested_map_round_trip(
953 entries in proptest::collection::hash_map(
954 any::<u64>(),
955 proptest::collection::hash_map(
956 any::<$K>(), any::<$V>(), 0..std::cmp::min($n, 20)
957 ),
958 1..10
959 ),
960 ) {
961 let outer: TlsMap<u64, TlsMap<$K, $V>> = entries
962 .into_iter()
963 .map(|(k, inner)| (k, inner.into_iter().collect()))
964 .collect();
965 let bytes = outer.tls_serialize_detached().unwrap();
966 let deserialized = TlsMap::<u64, TlsMap<$K, $V>>::tls_deserialize_exact(&bytes).unwrap();
967 prop_assert_eq!(outer, deserialized);
968 }
969
970 #[test]
972 fn nested_map_reverse_round_trip(
973 entries in proptest::collection::hash_map(
974 any::<$K>(),
975 proptest::collection::hash_map(
976 any::<u64>(), any::<$V>(), 0..20
977 ),
978 1..std::cmp::min($n, 10)
979 ),
980 ) {
981 let outer: TlsMap<$K, TlsMap<u64, $V>> = entries
982 .into_iter()
983 .map(|(k, inner)| (k, inner.into_iter().collect()))
984 .collect();
985 let bytes = outer.tls_serialize_detached().unwrap();
986 let deserialized = TlsMap::<$K, TlsMap<u64, $V>>::tls_deserialize_exact(&bytes).unwrap();
987 prop_assert_eq!(outer, deserialized);
988 }
989
990 #[test]
992 fn delta_round_trip(
993 mutations in proptest::collection::vec(
994 (any::<$K>(), any::<$V>(), 0u8..3), 0..20
995 )
996 ) {
997 let mut delta = TlsMapDelta::new();
998 for (key, value, tag) in mutations {
999 delta = match tag {
1000 0 => delta.insert(key, value),
1001 1 => delta.update(key, value),
1002 _ => delta.delete(key),
1003 };
1004 }
1005 let bytes = delta.tls_serialize_detached().unwrap();
1006 let rt = TlsMapDelta::<$K, $V>::tls_deserialize_exact(&bytes).unwrap();
1007 prop_assert_eq!(delta, rt);
1008 }
1009 }
1010
1011 #[test]
1013 fn empty_map_serializes_to_zero_length_prefix() {
1014 let map = TlsMap::<$K, $V>::new();
1015 assert_eq!(map.tls_serialize_detached().unwrap(), vec![0]);
1016 }
1017
1018 #[test]
1019 fn debug_format() {
1020 let key = <$K>::default();
1021 let value = <$V>::default();
1022 let entry = TlsMapEntry::<$K, $V> {
1023 key: key.clone(),
1024 value: value.clone(),
1025 };
1026 let expected = format!("{{ key: {:?}, value: {:?} }}", key, value);
1027 assert_eq!(format!("{:?}", entry), expected);
1028 }
1029
1030 #[test]
1031 fn get_mut_modifies_value() {
1032 let mut map = TlsMap::<$K, $V>::new();
1033 let key = <$K>::default();
1034 let value = <$V>::default();
1035 map.insert(key.clone(), value).unwrap();
1036 let v = map.get_mut(&key).unwrap();
1037 *v = ($mutate_v)(v.clone());
1038 assert_ne!(map.get(&key), Some(&<$V>::default()));
1039 }
1040
1041 #[test]
1042 fn iter_yields_all_pairs() {
1043 let mut map = TlsMap::<$K, $V>::new();
1044 map.set(<$K>::default(), <$V>::default());
1045 let pairs: Vec<_> = map.iter().collect();
1046 assert_eq!(pairs.len(), 1);
1047 assert_eq!(pairs[0], (&<$K>::default(), &<$V>::default()));
1048 }
1049
1050 #[test]
1051 fn values_yields_all_values() {
1052 let mut map = TlsMap::<$K, $V>::new();
1053 map.set(<$K>::default(), <$V>::default());
1054 let vals: Vec<_> = map.values().collect();
1055 assert_eq!(vals, vec![&<$V>::default()]);
1056 }
1057
1058 #[test]
1059 fn default_creates_empty() {
1060 let map = TlsMap::<$K, $V>::default();
1061 assert!(map.is_empty());
1062 let delta = TlsMapDelta::<$K, $V>::default();
1063 assert!(delta.mutations.is_empty());
1064 }
1065
1066 #[test]
1067 fn rejects_invalid_mutation_tag() {
1068 let mut bytes = Vec::new();
1069 let tag_byte = 3u8; let key = <$K>::default();
1071 let value = <$V>::default();
1072 let content_len = 1 + key.tls_serialized_len() + value.tls_serialized_len();
1073 tls_codec::vlen::write_length(&mut bytes, content_len).unwrap();
1074 tag_byte.tls_serialize(&mut bytes).unwrap();
1075 key.tls_serialize(&mut bytes).unwrap();
1076 value.tls_serialize(&mut bytes).unwrap();
1077 assert!(TlsMapDelta::<$K, $V>::tls_deserialize_exact(&bytes).is_err());
1078 }
1079
1080 #[test]
1082 fn rejects_unsorted_deterministic() {
1083 let key_lo = <$K>::default();
1086 let key_hi = {
1087 let mut kb = key_lo.tls_serialize_detached().unwrap();
1089 *kb.last_mut().unwrap() = kb.last().unwrap().wrapping_add(1);
1090 kb
1091 };
1092 let val = <$V>::default().tls_serialize_detached().unwrap();
1093 let mut content = Vec::new();
1095 content.extend_from_slice(&key_hi);
1096 content.extend_from_slice(&val);
1097 content.extend_from_slice(&key_lo.tls_serialize_detached().unwrap());
1098 content.extend_from_slice(&val);
1099 let mut bytes = Vec::new();
1100 tls_codec::vlen::write_length(&mut bytes, content.len()).unwrap();
1101 bytes.extend_from_slice(&content);
1102 let result = TlsMap::<$K, $V>::tls_deserialize_exact(&bytes);
1103 assert!(result.is_err(), "should reject unsorted entries");
1104 }
1105
1106 #[test]
1108 fn rejects_duplicates_deterministic() {
1109 let key = <$K>::default();
1110 let v1 = <$V>::default();
1111 let v2 = ($mutate_v)(<$V>::default());
1112 let mut content = Vec::new();
1113 key.tls_serialize(&mut content).unwrap();
1114 v1.tls_serialize(&mut content).unwrap();
1115 key.tls_serialize(&mut content).unwrap();
1116 v2.tls_serialize(&mut content).unwrap();
1117 let mut bytes = Vec::new();
1118 tls_codec::vlen::write_length(&mut bytes, content.len()).unwrap();
1119 bytes.extend_from_slice(&content);
1120 let result = TlsMap::<$K, $V>::tls_deserialize_exact(&bytes);
1121 assert!(result.is_err(), "should reject duplicate keys");
1122 }
1123
1124 #[test]
1126 fn rejects_trailing_bytes() {
1127 let mut map = TlsMap::<$K, $V>::new();
1128 map.set(<$K>::default(), <$V>::default());
1129 let mut bytes = map.tls_serialize_detached().unwrap();
1130 bytes.push(0xFF);
1131 assert!(TlsMap::<$K, $V>::tls_deserialize_exact(&bytes).is_err());
1132 }
1133 }
1134 };
1135 }
1136
1137 tls_map_tests!(u8_u8, u8, u8, 1000, |v: u8| v.wrapping_add(1));
1139 tls_map_tests!(u8_u16, u8, u16, 1000, |v: u16| v.wrapping_add(1));
1140 tls_map_tests!(u8_u32, u8, u32, 1000, |v: u32| v.wrapping_add(1));
1141 tls_map_tests!(u8_u64, u8, u64, 1000, |v: u64| v.wrapping_add(1));
1142 tls_map_tests!(u16_u8, u16, u8, 1000, |v: u8| v.wrapping_add(1));
1143 tls_map_tests!(u16_u16, u16, u16, 1000, |v: u16| v.wrapping_add(1));
1144 tls_map_tests!(u16_u32, u16, u32, 1000, |v: u32| v.wrapping_add(1));
1145 tls_map_tests!(u16_u64, u16, u64, 1000, |v: u64| v.wrapping_add(1));
1146 tls_map_tests!(u32_u8, u32, u8, 1000, |v: u8| v.wrapping_add(1));
1147 tls_map_tests!(u32_u16, u32, u16, 1000, |v: u16| v.wrapping_add(1));
1148 tls_map_tests!(u32_u32, u32, u32, 1000, |v: u32| v.wrapping_add(1));
1149 tls_map_tests!(u32_u64, u32, u64, 1000, |v: u64| v.wrapping_add(1));
1150 tls_map_tests!(u64_u8, u64, u8, 1000, |v: u8| v.wrapping_add(1));
1151 tls_map_tests!(u64_u16, u64, u16, 1000, |v: u16| v.wrapping_add(1));
1152 tls_map_tests!(u64_u32, u64, u32, 1000, |v: u32| v.wrapping_add(1));
1153 tls_map_tests!(u64_u64, u64, u64, 1000, |v: u64| v.wrapping_add(1));
1154 tls_map_tests!(u16_32_bytes, u16, [u8; 32], 1000, |v: [u8; 32]| {
1155 let mut v = v;
1156 v[0] = v[0].wrapping_add(1);
1157 v
1158 });
1159 tls_map_tests!(u64_vec, u64, Vec<u8>, 1000, |v: Vec<u8>| {
1160 let mut v = v;
1161 v.push(42);
1162 v
1163 });
1164 tls_map_tests!(_32_bytes_vec, [u8; 32], Vec<u8>, 1000, |v: Vec<u8>| {
1165 let mut v = v;
1166 v.push(1);
1167 v
1168 });
1169 tls_map_tests!(vec_vec, Vec<u8>, Vec<u8>, 1000, |v: Vec<u8>| {
1170 let mut v = v;
1171 v.push(2);
1172 v
1173 });
1174}