1#[cfg(not(feature = "preserve_order"))]
12use alloc::collections::{BTreeMap, btree_map};
13use core::borrow::Borrow;
14use core::fmt::{self, Debug};
15use core::hash::Hash;
16use core::iter::FusedIterator;
17use core::ops;
18use std::marker::PhantomData;
19
20#[cfg(feature = "preserve_order")]
21use indexmap::IndexMap;
22use scuffle_bytes_util::StringCow;
23use serde::de;
24
25use crate::{Amf0Error, Amf0Value};
26
27#[derive(Clone, PartialEq)]
29pub struct Amf0Object<'a> {
30 map: MapImpl<StringCow<'a>, Amf0Value<'a>>,
31}
32
33#[cfg(not(feature = "preserve_order"))]
34type MapImpl<K, V> = BTreeMap<K, V>;
35#[cfg(feature = "preserve_order")]
36type MapImpl<K, V> = IndexMap<K, V>;
37
38impl<'a> Default for Amf0Object<'a> {
39 fn default() -> Self {
40 Self::new()
41 }
42}
43
44impl<'a> Amf0Object<'a> {
45 #[inline]
47 pub fn new() -> Self {
48 Amf0Object { map: MapImpl::new() }
49 }
50
51 #[inline]
53 pub fn with_capacity(capacity: usize) -> Self {
54 Amf0Object {
55 #[cfg(not(feature = "preserve_order"))]
56 map: {
57 let _ = capacity;
59 BTreeMap::new()
60 },
61 #[cfg(feature = "preserve_order")]
62 map: IndexMap::with_capacity(capacity),
63 }
64 }
65
66 #[inline]
68 pub fn clear(&mut self) {
69 self.map.clear();
70 }
71
72 #[inline]
77 pub fn get<Q>(&self, key: &Q) -> Option<&Amf0Value<'a>>
78 where
79 StringCow<'a>: Borrow<Q>,
80 Q: ?Sized + Ord + Eq + Hash,
81 {
82 self.map.get(key)
83 }
84
85 #[inline]
90 pub fn contains_key<Q>(&self, key: &Q) -> bool
91 where
92 StringCow<'a>: Borrow<Q>,
93 Q: ?Sized + Ord + Eq + Hash,
94 {
95 self.map.contains_key(key)
96 }
97
98 #[inline]
103 pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut Amf0Value<'a>>
104 where
105 StringCow<'a>: Borrow<Q>,
106 Q: ?Sized + Ord + Eq + Hash,
107 {
108 self.map.get_mut(key)
109 }
110
111 #[inline]
116 pub fn get_key_value<Q>(&self, key: &Q) -> Option<(&StringCow<'a>, &Amf0Value<'a>)>
117 where
118 StringCow<'a>: Borrow<Q>,
119 Q: ?Sized + Ord + Eq + Hash,
120 {
121 self.map.get_key_value(key)
122 }
123
124 #[inline]
131 pub fn insert(&mut self, k: StringCow<'a>, v: Amf0Value<'a>) -> Option<Amf0Value<'a>> {
132 self.map.insert(k, v)
133 }
134
135 #[cfg(feature = "preserve_order")]
142 #[inline]
143 pub fn shift_insert(&mut self, index: usize, k: StringCow<'a>, v: Amf0Value<'a>) -> Option<Amf0Value<'a>> {
144 self.map.shift_insert(index, k, v)
145 }
146
147 #[inline]
159 pub fn remove<Q>(&mut self, key: &Q) -> Option<Amf0Value<'a>>
160 where
161 StringCow<'a>: Borrow<Q>,
162 Q: ?Sized + Ord + Eq + Hash,
163 {
164 #[cfg(feature = "preserve_order")]
165 return self.swap_remove(key);
166 #[cfg(not(feature = "preserve_order"))]
167 return self.map.remove(key);
168 }
169
170 #[inline]
182 pub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(StringCow<'a>, Amf0Value<'a>)>
183 where
184 StringCow<'a>: Borrow<Q>,
185 Q: ?Sized + Ord + Eq + Hash,
186 {
187 #[cfg(feature = "preserve_order")]
188 return self.swap_remove_entry(key);
189 #[cfg(not(feature = "preserve_order"))]
190 return self.map.remove_entry(key);
191 }
192
193 #[cfg(feature = "preserve_order")]
201 #[inline]
202 pub fn swap_remove<Q>(&mut self, key: &Q) -> Option<Amf0Value<'a>>
203 where
204 StringCow<'a>: Borrow<Q>,
205 Q: ?Sized + Ord + Eq + Hash,
206 {
207 self.map.swap_remove(key)
208 }
209
210 #[cfg(feature = "preserve_order")]
218 #[inline]
219 pub fn swap_remove_entry<Q>(&mut self, key: &Q) -> Option<(StringCow<'a>, Amf0Value<'a>)>
220 where
221 StringCow<'a>: Borrow<Q>,
222 Q: ?Sized + Ord + Eq + Hash,
223 {
224 self.map.swap_remove_entry(key)
225 }
226
227 #[cfg(feature = "preserve_order")]
235 #[inline]
236 pub fn shift_remove<Q>(&mut self, key: &Q) -> Option<Amf0Value<'a>>
237 where
238 StringCow<'a>: Borrow<Q>,
239 Q: ?Sized + Ord + Eq + Hash,
240 {
241 self.map.shift_remove(key)
242 }
243
244 #[cfg(feature = "preserve_order")]
252 #[inline]
253 pub fn shift_remove_entry<Q>(&mut self, key: &Q) -> Option<(StringCow<'a>, Amf0Value<'a>)>
254 where
255 StringCow<'a>: Borrow<Q>,
256 Q: ?Sized + Ord + Eq + Hash,
257 {
258 self.map.shift_remove_entry(key)
259 }
260
261 #[inline]
263 pub fn append(&mut self, other: &mut Self) {
264 #[cfg(feature = "preserve_order")]
265 self.map.extend(std::mem::take(&mut other.map));
266 #[cfg(not(feature = "preserve_order"))]
267 self.map.append(&mut other.map);
268 }
269
270 pub fn entry(&mut self, key: impl Into<StringCow<'a>>) -> Entry<'_, 'a> {
273 #[cfg(not(feature = "preserve_order"))]
274 use alloc::collections::btree_map::Entry as EntryImpl;
275
276 #[cfg(feature = "preserve_order")]
277 use indexmap::map::Entry as EntryImpl;
278
279 match self.map.entry(key.into()) {
280 EntryImpl::Vacant(vacant) => Entry::Vacant(VacantEntry { vacant }),
281 EntryImpl::Occupied(occupied) => Entry::Occupied(OccupiedEntry { occupied }),
282 }
283 }
284
285 #[inline]
287 pub fn len(&self) -> usize {
288 self.map.len()
289 }
290
291 #[inline]
293 pub fn is_empty(&self) -> bool {
294 self.map.is_empty()
295 }
296
297 #[inline]
299 pub fn iter(&self) -> Iter<'_, 'a> {
300 Iter { iter: self.map.iter() }
301 }
302
303 #[inline]
305 pub fn iter_mut(&mut self) -> IterMut<'_, 'a> {
306 IterMut {
307 iter: self.map.iter_mut(),
308 }
309 }
310
311 #[inline]
313 pub fn keys(&self) -> Keys<'_, 'a> {
314 Keys { iter: self.map.keys() }
315 }
316
317 #[inline]
319 pub fn values(&self) -> Values<'_, 'a> {
320 Values { iter: self.map.values() }
321 }
322
323 #[inline]
325 pub fn values_mut(&mut self) -> ValuesMut<'_, 'a> {
326 ValuesMut {
327 iter: self.map.values_mut(),
328 }
329 }
330
331 #[inline]
333 pub fn into_values(self) -> IntoValues<'a> {
334 IntoValues {
335 iter: self.map.into_values(),
336 }
337 }
338
339 #[inline]
344 pub fn retain<F>(&mut self, f: F)
345 where
346 F: FnMut(&StringCow<'a>, &mut Amf0Value<'a>) -> bool,
347 {
348 self.map.retain(f);
349 }
350
351 #[inline]
362 pub fn sort_keys(&mut self) {
363 #[cfg(feature = "preserve_order")]
364 self.map.sort_unstable_keys();
365 }
366}
367
368impl<'a, Q> ops::Index<&Q> for Amf0Object<'a>
383where
384 StringCow<'a>: Borrow<Q>,
385 Q: ?Sized + Ord + Eq + Hash,
386{
387 type Output = Amf0Value<'a>;
388
389 fn index(&self, index: &Q) -> &Self::Output {
390 self.map.index(index)
391 }
392}
393
394impl<'a, Q> ops::IndexMut<&Q> for Amf0Object<'a>
397where
398 StringCow<'a>: Borrow<Q>,
399 Q: ?Sized + Ord + Eq + Hash,
400{
401 fn index_mut(&mut self, index: &Q) -> &mut Self::Output {
402 self.map.get_mut(index).expect("no entry found for key")
403 }
404}
405
406impl Debug for Amf0Object<'_> {
407 #[inline]
408 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
409 self.map.fmt(formatter)
410 }
411}
412
413#[cfg(feature = "serde")]
414impl serde::ser::Serialize for Amf0Object<'_> {
415 #[inline]
416 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
417 where
418 S: serde::ser::Serializer,
419 {
420 use serde::ser::SerializeMap;
421 let mut map = serializer.serialize_map(Some(self.len()))?;
422 for (k, v) in self {
423 map.serialize_entry(k, v)?;
424 }
425 map.end()
426 }
427}
428
429#[cfg(feature = "serde")]
430impl<'de> de::Deserialize<'de> for Amf0Object<'de> {
431 #[inline]
432 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
433 where
434 D: de::Deserializer<'de>,
435 {
436 struct Visitor;
437
438 impl<'de> de::Visitor<'de> for Visitor {
439 type Value = Amf0Object<'de>;
440
441 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
442 formatter.write_str("a map")
443 }
444
445 #[inline]
446 fn visit_unit<E>(self) -> Result<Self::Value, E>
447 where
448 E: de::Error,
449 {
450 Ok(Amf0Object::new())
451 }
452
453 #[inline]
454 fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
455 where
456 V: de::MapAccess<'de>,
457 {
458 let mut values = Amf0Object::new();
459
460 while let Some((key, value)) = visitor.next_entry()? {
461 values.insert(key, value);
462 }
463
464 Ok(values)
465 }
466 }
467
468 deserializer.deserialize_map(Visitor)
469 }
470}
471
472impl<'a> FromIterator<(StringCow<'a>, Amf0Value<'a>)> for Amf0Object<'a> {
473 fn from_iter<T>(iter: T) -> Self
474 where
475 T: IntoIterator<Item = (StringCow<'a>, Amf0Value<'a>)>,
476 {
477 Amf0Object {
478 map: FromIterator::from_iter(iter),
479 }
480 }
481}
482
483impl<'a> Extend<(StringCow<'a>, Amf0Value<'a>)> for Amf0Object<'a> {
484 fn extend<T>(&mut self, iter: T)
485 where
486 T: IntoIterator<Item = (StringCow<'a>, Amf0Value<'a>)>,
487 {
488 self.map.extend(iter);
489 }
490}
491
492macro_rules! delegate_iterator {
493 (($name:ident $($generics:tt)*) => $item:ty) => {
494 impl $($generics)* Iterator for $name $($generics)* {
495 type Item = $item;
496 #[inline]
497 fn next(&mut self) -> Option<Self::Item> {
498 self.iter.next()
499 }
500 #[inline]
501 fn size_hint(&self) -> (usize, Option<usize>) {
502 self.iter.size_hint()
503 }
504 }
505
506 impl $($generics)* DoubleEndedIterator for $name $($generics)* {
507 #[inline]
508 fn next_back(&mut self) -> Option<Self::Item> {
509 self.iter.next_back()
510 }
511 }
512
513 impl $($generics)* ExactSizeIterator for $name $($generics)* {
514 #[inline]
515 fn len(&self) -> usize {
516 self.iter.len()
517 }
518 }
519
520 impl $($generics)* FusedIterator for $name $($generics)* {}
521 }
522}
523
524#[cfg(feature = "serde")]
525impl<'de> de::IntoDeserializer<'de, Amf0Error> for Amf0Object<'de> {
526 type Deserializer = Self;
527
528 fn into_deserializer(self) -> Self::Deserializer {
529 self
530 }
531}
532
533#[cfg(feature = "serde")]
534impl<'de> de::IntoDeserializer<'de, Amf0Error> for &'de Amf0Object<'de> {
535 type Deserializer = Self;
536
537 fn into_deserializer(self) -> Self::Deserializer {
538 self
539 }
540}
541
542#[cfg(feature = "serde")]
543impl<'de> serde::de::Deserializer<'de> for Amf0Object<'de> {
544 type Error = Amf0Error;
545
546 serde::forward_to_deserialize_any! {
547 bool f64 f32 char str string unit
548 i8 i16 i32 i64 u8 u16 u32 u64
549 seq map newtype_struct tuple
550 struct enum ignored_any identifier
551 bytes byte_buf option unit_struct
552 tuple_struct
553 }
554
555 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
556 where
557 V: de::Visitor<'de>,
558 {
559 visitor.visit_map(Amf0MapAccess {
560 iter: self.into_iter(),
561 _phantom: PhantomData,
562 value: None,
563 })
564 }
565}
566
567#[cfg(feature = "serde")]
568impl<'de> serde::de::Deserializer<'de> for &'de Amf0Object<'de> {
569 type Error = Amf0Error;
570
571 serde::forward_to_deserialize_any! {
572 bool f64 f32 char str string unit
573 i8 i16 i32 i64 u8 u16 u32 u64
574 seq map newtype_struct tuple
575 struct enum ignored_any identifier
576 bytes byte_buf option unit_struct
577 tuple_struct
578 }
579
580 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
581 where
582 V: de::Visitor<'de>,
583 {
584 visitor.visit_map(Amf0MapAccess {
585 iter: self.into_iter(),
586 _phantom: PhantomData,
587 value: None,
588 })
589 }
590}
591
592#[cfg(feature = "serde")]
593struct Amf0MapAccess<I, K, V> {
594 iter: I,
595 value: Option<V>,
596 _phantom: PhantomData<K>,
597}
598
599#[cfg(feature = "serde")]
600impl<'de, I, K, V> serde::de::MapAccess<'de> for Amf0MapAccess<I, K, V>
601where
602 I: Iterator<Item = (K, V)>,
603 K: serde::de::IntoDeserializer<'de, Amf0Error>,
604 V: serde::de::IntoDeserializer<'de, Amf0Error>,
605{
606 type Error = Amf0Error;
607
608 fn next_key_seed<S>(&mut self, seed: S) -> Result<Option<S::Value>, Self::Error>
609 where
610 S: serde::de::DeserializeSeed<'de>,
611 {
612 match self.iter.next() {
613 Some((key, value)) => {
614 self.value = Some(value);
615 seed.deserialize(key.into_deserializer()).map(Some)
616 }
617 None => Ok(None),
618 }
619 }
620
621 fn next_value_seed<S>(&mut self, seed: S) -> Result<S::Value, Self::Error>
622 where
623 S: serde::de::DeserializeSeed<'de>,
624 {
625 seed.deserialize(self.value.take().unwrap().into_deserializer())
626 }
627}
628
629pub enum Entry<'a, 'b> {
636 Vacant(VacantEntry<'a, 'b>),
638 Occupied(OccupiedEntry<'a, 'b>),
640}
641
642pub struct VacantEntry<'a, 'b> {
644 vacant: VacantEntryImpl<'a, 'b>,
645}
646
647pub struct OccupiedEntry<'a, 'b> {
649 occupied: OccupiedEntryImpl<'a, 'b>,
650}
651
652#[cfg(not(feature = "preserve_order"))]
653type VacantEntryImpl<'a, 'b> = btree_map::VacantEntry<'a, StringCow<'b>, Amf0Value<'b>>;
654#[cfg(feature = "preserve_order")]
655type VacantEntryImpl<'a, 'b> = indexmap::map::VacantEntry<'a, StringCow<'b>, Amf0Value<'b>>;
656
657#[cfg(not(feature = "preserve_order"))]
658type OccupiedEntryImpl<'a, 'b> = btree_map::OccupiedEntry<'a, StringCow<'b>, Amf0Value<'b>>;
659#[cfg(feature = "preserve_order")]
660type OccupiedEntryImpl<'a, 'b> = indexmap::map::OccupiedEntry<'a, StringCow<'b>, Amf0Value<'b>>;
661
662impl<'a, 'b> Entry<'a, 'b> {
663 pub fn key(&self) -> &StringCow<'b> {
672 match self {
673 Entry::Vacant(e) => e.key(),
674 Entry::Occupied(e) => e.key(),
675 }
676 }
677
678 pub fn or_insert(self, default: Amf0Value<'b>) -> &'a mut Amf0Value<'b> {
681 match self {
682 Entry::Vacant(entry) => entry.insert(default),
683 Entry::Occupied(entry) => entry.into_mut(),
684 }
685 }
686
687 pub fn or_insert_with<F>(self, default: F) -> &'a mut Amf0Value<'b>
691 where
692 F: FnOnce() -> Amf0Value<'b>,
693 {
694 match self {
695 Entry::Vacant(entry) => entry.insert(default()),
696 Entry::Occupied(entry) => entry.into_mut(),
697 }
698 }
699
700 pub fn and_modify<F>(self, f: F) -> Self
703 where
704 F: FnOnce(&mut Amf0Value<'b>),
705 {
706 match self {
707 Entry::Occupied(mut entry) => {
708 f(entry.get_mut());
709 Entry::Occupied(entry)
710 }
711 Entry::Vacant(entry) => Entry::Vacant(entry),
712 }
713 }
714}
715
716impl<'a, 'b> VacantEntry<'a, 'b> {
717 #[inline]
735 pub fn key(&self) -> &StringCow<'b> {
736 self.vacant.key()
737 }
738
739 #[inline]
742 pub fn insert(self, value: Amf0Value<'b>) -> &'a mut Amf0Value<'b> {
743 self.vacant.insert(value)
744 }
745}
746
747impl<'a, 'b> OccupiedEntry<'a, 'b> {
748 #[inline]
750 pub fn key(&self) -> &StringCow<'b> {
751 self.occupied.key()
752 }
753
754 #[inline]
756 pub fn get(&self) -> &Amf0Value<'b> {
757 self.occupied.get()
758 }
759
760 #[inline]
762 pub fn get_mut(&mut self) -> &mut Amf0Value<'b> {
763 self.occupied.get_mut()
764 }
765
766 #[inline]
768 pub fn into_mut(self) -> &'a mut Amf0Value<'b> {
769 self.occupied.into_mut()
770 }
771
772 #[inline]
775 pub fn insert(&mut self, value: Amf0Value<'b>) -> Amf0Value<'b> {
776 self.occupied.insert(value)
777 }
778
779 #[inline]
787 pub fn remove(self) -> Amf0Value<'b> {
788 #[cfg(feature = "preserve_order")]
789 return self.swap_remove();
790 #[cfg(not(feature = "preserve_order"))]
791 return self.occupied.remove();
792 }
793
794 #[cfg(feature = "preserve_order")]
802 #[inline]
803 pub fn swap_remove(self) -> Amf0Value<'b> {
804 self.occupied.swap_remove()
805 }
806
807 #[cfg(feature = "preserve_order")]
815 #[inline]
816 pub fn shift_remove(self) -> Amf0Value<'b> {
817 self.occupied.shift_remove()
818 }
819
820 #[inline]
828 pub fn remove_entry(self) -> (StringCow<'b>, Amf0Value<'b>) {
829 #[cfg(feature = "preserve_order")]
830 return self.swap_remove_entry();
831 #[cfg(not(feature = "preserve_order"))]
832 return self.occupied.remove_entry();
833 }
834
835 #[cfg(feature = "preserve_order")]
843 #[inline]
844 pub fn swap_remove_entry(self) -> (StringCow<'b>, Amf0Value<'b>) {
845 self.occupied.swap_remove_entry()
846 }
847
848 #[cfg(feature = "preserve_order")]
856 #[inline]
857 pub fn shift_remove_entry(self) -> (StringCow<'b>, Amf0Value<'b>) {
858 self.occupied.shift_remove_entry()
859 }
860}
861
862impl<'a, 'b> IntoIterator for &'a Amf0Object<'b> {
865 type IntoIter = Iter<'a, 'b>;
866 type Item = (&'a StringCow<'b>, &'a Amf0Value<'b>);
867
868 #[inline]
869 fn into_iter(self) -> Self::IntoIter {
870 Iter { iter: self.map.iter() }
871 }
872}
873
874pub struct Iter<'a, 'b> {
876 iter: IterImpl<'a, 'b>,
877}
878
879#[cfg(not(feature = "preserve_order"))]
880type IterImpl<'a, 'b> = btree_map::Iter<'a, StringCow<'b>, Amf0Value<'b>>;
881#[cfg(feature = "preserve_order")]
882type IterImpl<'a, 'b> = indexmap::map::Iter<'a, StringCow<'b>, Amf0Value<'b>>;
883
884delegate_iterator!((Iter<'a, 'b>) => (&'a StringCow<'b>, &'a Amf0Value<'b>));
885
886impl<'a, 'b> IntoIterator for &'a mut Amf0Object<'b> {
889 type IntoIter = IterMut<'a, 'b>;
890 type Item = (&'a StringCow<'b>, &'a mut Amf0Value<'b>);
891
892 #[inline]
893 fn into_iter(self) -> Self::IntoIter {
894 IterMut {
895 iter: self.map.iter_mut(),
896 }
897 }
898}
899
900pub struct IterMut<'a, 'b> {
902 iter: IterMutImpl<'a, 'b>,
903}
904
905#[cfg(not(feature = "preserve_order"))]
906type IterMutImpl<'a, 'b> = btree_map::IterMut<'a, StringCow<'b>, Amf0Value<'b>>;
907#[cfg(feature = "preserve_order")]
908type IterMutImpl<'a, 'b> = indexmap::map::IterMut<'a, StringCow<'b>, Amf0Value<'b>>;
909
910delegate_iterator!((IterMut<'a, 'b>) => (&'a StringCow<'b>, &'a mut Amf0Value<'b>));
911
912impl<'a> IntoIterator for Amf0Object<'a> {
915 type IntoIter = IntoIter<'a>;
916 type Item = (StringCow<'a>, Amf0Value<'a>);
917
918 #[inline]
919 fn into_iter(self) -> Self::IntoIter {
920 IntoIter {
921 iter: self.map.into_iter(),
922 }
923 }
924}
925
926pub struct IntoIter<'a> {
928 iter: IntoIterImpl<'a>,
929}
930
931#[cfg(not(feature = "preserve_order"))]
932type IntoIterImpl<'a> = btree_map::IntoIter<StringCow<'a>, Amf0Value<'a>>;
933#[cfg(feature = "preserve_order")]
934type IntoIterImpl<'a> = indexmap::map::IntoIter<StringCow<'a>, Amf0Value<'a>>;
935
936delegate_iterator!((IntoIter<'a>) => (StringCow<'a>, Amf0Value<'a>));
937
938pub struct Keys<'a, 'b> {
942 iter: KeysImpl<'a, 'b>,
943}
944
945#[cfg(not(feature = "preserve_order"))]
946type KeysImpl<'a, 'b> = btree_map::Keys<'a, StringCow<'b>, Amf0Value<'b>>;
947#[cfg(feature = "preserve_order")]
948type KeysImpl<'a, 'b> = indexmap::map::Keys<'a, StringCow<'b>, Amf0Value<'b>>;
949
950delegate_iterator!((Keys<'a, 'b>) => &'a StringCow<'b>);
951
952pub struct Values<'a, 'b> {
956 iter: ValuesImpl<'a, 'b>,
957}
958
959#[cfg(not(feature = "preserve_order"))]
960type ValuesImpl<'a, 'b> = btree_map::Values<'a, StringCow<'b>, Amf0Value<'b>>;
961#[cfg(feature = "preserve_order")]
962type ValuesImpl<'a, 'b> = indexmap::map::Values<'a, StringCow<'b>, Amf0Value<'b>>;
963
964delegate_iterator!((Values<'a, 'b>) => &'a Amf0Value<'b>);
965
966pub struct ValuesMut<'a, 'b> {
970 iter: ValuesMutImpl<'a, 'b>,
971}
972
973#[cfg(not(feature = "preserve_order"))]
974type ValuesMutImpl<'a, 'b> = btree_map::ValuesMut<'a, StringCow<'b>, Amf0Value<'b>>;
975#[cfg(feature = "preserve_order")]
976type ValuesMutImpl<'a, 'b> = indexmap::map::ValuesMut<'a, StringCow<'b>, Amf0Value<'b>>;
977
978delegate_iterator!((ValuesMut<'a, 'b>) => &'a mut Amf0Value<'b>);
979
980pub struct IntoValues<'a> {
984 iter: IntoValuesImpl<'a>,
985}
986
987#[cfg(not(feature = "preserve_order"))]
988type IntoValuesImpl<'a> = btree_map::IntoValues<StringCow<'a>, Amf0Value<'a>>;
989#[cfg(feature = "preserve_order")]
990type IntoValuesImpl<'a> = indexmap::map::IntoValues<StringCow<'a>, Amf0Value<'a>>;
991
992delegate_iterator!((IntoValues<'a>) => Amf0Value<'a>);
993
994#[cfg(test)]
995#[cfg_attr(all(test, coverage_nightly), coverage(off))]
996mod tests {
997 use scuffle_bytes_util::StringCow;
998 use serde::Deserialize;
999
1000 use super::Entry;
1001 use crate::{Amf0Object, Amf0Value};
1002
1003 #[test]
1004 fn test_default_map_is_empty() {
1005 let obj: Amf0Object = Amf0Object::default();
1006 assert!(obj.map.is_empty(), "Default Amf0Object should be empty");
1007 }
1008
1009 #[cfg(feature = "preserve_order")]
1010 #[test]
1011 fn test_capacity_reserves_space_in_preserve_order() {
1012 let capacity = 16;
1013 let obj: Amf0Object = Amf0Object::with_capacity(capacity);
1014
1015 use indexmap::map::IndexMap;
1016 let map: &IndexMap<_, _> = &obj.map;
1017 assert!(
1018 map.capacity() >= capacity,
1019 "IndexMap should reserve at least the requested capacity"
1020 );
1021 }
1022
1023 #[cfg(not(feature = "preserve_order"))]
1024 #[test]
1025 fn test_capacity_ignored_without_preserve_order() {
1026 let capacity = 16;
1027 let obj: Amf0Object = Amf0Object::with_capacity(capacity);
1028
1029 let key = StringCow::from("foo");
1030 let value = Amf0Value::String(StringCow::from("bar"));
1031 assert!(obj.map.insert(key.clone(), value.clone()).is_none());
1032 assert_eq!(obj.map.get(&key), Some(&value));
1033 }
1034
1035 #[test]
1036 fn test_clear() {
1037 let mut obj = Amf0Object::new();
1038
1039 obj.map.insert(StringCow::from("key1"), Amf0Value::Number(1.0));
1040 obj.map
1041 .insert(StringCow::from("key2"), Amf0Value::String(StringCow::from("value")));
1042 obj.map.insert(StringCow::from("key3"), Amf0Value::Boolean(true));
1043
1044 assert!(!obj.map.is_empty(), "Map should not be empty before clear");
1045 obj.clear();
1046 assert!(obj.map.is_empty(), "Map should be empty after clear");
1047 }
1048
1049 #[test]
1050 fn test_contains_key() {
1051 let mut obj = Amf0Object::new();
1052
1053 let existing_key = StringCow::from("present");
1054 let missing_key = "missing";
1055
1056 obj.map.insert(existing_key.clone(), Amf0Value::Boolean(true));
1057
1058 assert!(obj.contains_key(&existing_key), "Expected key to be found using StringCow");
1059 assert!(obj.contains_key("present"), "Expected key to be found using &str");
1060 assert!(!obj.contains_key(missing_key), "Expected missing key to not be found");
1061 }
1062
1063 #[test]
1064 fn test_get_mut_valid() {
1065 let mut obj = Amf0Object::new();
1066 obj.map
1067 .insert(StringCow::from("username"), Amf0Value::String(StringCow::from("old_name")));
1068
1069 if let Some(value) = obj.get_mut("username") {
1070 *value = Amf0Value::String(StringCow::from("new_name"));
1071 } else {
1072 panic!("Expected Some(&mut Amf0Value) for existing key");
1073 }
1074
1075 assert_eq!(obj.map.get("username"), Some(&Amf0Value::String(StringCow::from("new_name"))));
1076 }
1077
1078 #[test]
1079 fn test_get_mut_invalid() {
1080 let mut obj = Amf0Object::new();
1081 assert!(obj.get_mut("nonexistent_key").is_none());
1082 }
1083
1084 #[test]
1085 fn test_get_key_value_valid() {
1086 let mut obj = Amf0Object::new();
1087 let key = StringCow::from("foo");
1088 let value = Amf0Value::Number(3.21);
1089
1090 obj.map.insert(key.clone(), value.clone());
1091
1092 if let Some((found_key, found_value)) = obj.get_key_value("foo") {
1093 assert_eq!(found_key, &key);
1094 assert_eq!(found_value, &value);
1095 } else {
1096 panic!("Expected Some((key, value)) for existing key");
1097 }
1098 }
1099
1100 #[test]
1101 fn test_get_key_value_invalid() {
1102 let obj = Amf0Object::new();
1103 assert!(obj.get_key_value("missing").is_none());
1104 }
1105
1106 #[cfg(feature = "preserve_order")]
1107 #[test]
1108 fn test_shift_insert_inserts_and_shifts_correctly() {
1109 let mut obj = Amf0Object::new();
1110
1111 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1112 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1113 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1114
1115 let ret_new = obj.shift_insert(1, StringCow::from("x"), Amf0Value::Number(9.0));
1116 assert!(ret_new.is_none(), "Inserting a brand‐new key should return None");
1117
1118 let keys_after_insert: Vec<&str> = obj.map.keys().map(|k| k.as_ref()).collect();
1119 assert_eq!(
1120 keys_after_insert,
1121 vec!["a", "x", "b", "c"],
1122 "After shifting in 'x' at index 1, order should be [\"a\", \"x\", \"b\", \"c\"]"
1123 );
1124
1125 let old_value = obj.shift_insert(0, StringCow::from("b"), Amf0Value::Number(7.0));
1126 assert_eq!(
1127 old_value,
1128 Some(Amf0Value::Number(2.0)),
1129 "Reinserting 'b' must return its previous value"
1130 );
1131
1132 let keys_after_reinsert: Vec<&str> = obj.map.keys().map(|k| k.as_ref()).collect();
1133 assert_eq!(
1134 keys_after_reinsert,
1135 vec!["b", "a", "x", "c"],
1136 "After shifting 'b' to index 0, order should be [\"b\", \"a\", \"x\", \"c\"]"
1137 );
1138
1139 assert_eq!(
1140 obj.map.get("b"),
1141 Some(&Amf0Value::Number(7.0)),
1142 "The value for key 'b' should now be updated to 7.0"
1143 );
1144 }
1145
1146 #[test]
1147 #[cfg(not(feature = "preserve_order"))]
1148 fn test_remove_non_preserve_order() {
1149 let mut obj = Amf0Object::new();
1150
1151 obj.map.insert(StringCow::from("key1"), Amf0Value::Number(10.0));
1152 obj.map
1153 .insert(StringCow::from("key2"), Amf0Value::String(StringCow::from("value")));
1154 obj.map.insert(StringCow::from("key3"), Amf0Value::Boolean(false));
1155
1156 let removed = obj.remove("key2");
1157 assert_eq!(
1158 removed,
1159 Some(Amf0Value::String(StringCow::from("value"))),
1160 "remove should return the value for an existing key"
1161 );
1162
1163 assert!(!obj.map.contains_key("key2"), "key2 should no longer exist after removal");
1164 assert!(
1165 obj.remove("missing").is_none(),
1166 "remove on a nonexistent key should return None"
1167 );
1168 }
1169
1170 #[test]
1171 #[cfg(feature = "preserve_order")]
1172 fn test_remove_preserve_order_swap_remove_behavior() {
1173 let mut obj = Amf0Object::new();
1174
1175 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1176 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1177 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1178
1179 let removed = obj.remove("b");
1180 assert_eq!(
1181 removed,
1182 Some(Amf0Value::Number(2.0)),
1183 "remove should return the old value for key 'b'"
1184 );
1185
1186 let keys_after: Vec<&str> = obj.map.keys().map(|k| k.as_ref()).collect();
1187 assert_eq!(
1188 keys_after,
1189 vec!["a", "c"],
1190 "After removing 'b', the order should be [\"a\", \"c\"]"
1191 );
1192 assert!(!obj.map.contains_key("b"), "key 'b' should be gone after removal");
1193 assert!(obj.map.contains_key("c"), "key 'c' should still be present");
1194 assert!(
1195 obj.remove("missing").is_none(),
1196 "remove on a nonexistent key should return None"
1197 );
1198 }
1199
1200 #[test]
1201 #[cfg(not(feature = "preserve_order"))]
1202 fn test_remove_entry_non_preserve_order() {
1203 let mut obj = Amf0Object::new();
1204
1205 obj.map.insert(StringCow::from("k1"), Amf0Value::Number(1.0));
1206 obj.map
1207 .insert(StringCow::from("k2"), Amf0Value::String(StringCow::from("v2")));
1208 obj.map.insert(StringCow::from("k3"), Amf0Value::Boolean(true));
1209
1210 let entry = obj.remove_entry("k2");
1211 assert_eq!(
1212 entry,
1213 Some((StringCow::from("k2"), Amf0Value::String(StringCow::from("v2")))),
1214 "Expected remove_entry to return the removed key and value"
1215 );
1216
1217 assert!(!obj.map.contains_key("k2"), "Key 'k2' should be gone after remove_entry");
1218 assert!(
1219 obj.remove_entry("missing").is_none(),
1220 "remove_entry on nonexistent key should return None"
1221 );
1222 }
1223
1224 #[test]
1225 #[cfg(feature = "preserve_order")]
1226 fn test_remove_entry_preserve_order_swap_remove_entry() {
1227 let mut obj = Amf0Object::new();
1228
1229 obj.map.insert(StringCow::from("a"), Amf0Value::Number(10.0));
1230 obj.map.insert(StringCow::from("b"), Amf0Value::Number(20.0));
1231 obj.map.insert(StringCow::from("c"), Amf0Value::Number(30.0));
1232 obj.map.insert(StringCow::from("d"), Amf0Value::Number(40.0));
1233
1234 let entry = obj.remove_entry("b");
1235 assert_eq!(
1236 entry,
1237 Some((StringCow::from("b"), Amf0Value::Number(20.0))),
1238 "Expected remove_entry to return the removed key 'b' and its value"
1239 );
1240
1241 let keys_after: Vec<&str> = obj.map.keys().map(|k| k.as_ref()).collect();
1242 assert_eq!(
1243 keys_after,
1244 vec!["a", "d", "c"],
1245 "After swap_remove_entry on 'b', order should be [\"a\", \"d\", \"c\"]"
1246 );
1247 assert!(!obj.map.contains_key("b"), "Key 'b' should be gone after remove_entry");
1248 assert!(obj.map.contains_key("d"), "Key 'd' should still be present");
1249 assert!(obj.map.contains_key("c"), "Key 'c' should still be present");
1250 assert!(
1251 obj.remove_entry("missing").is_none(),
1252 "remove_entry on nonexistent key should return None"
1253 );
1254 }
1255
1256 #[test]
1257 #[cfg(feature = "preserve_order")]
1258 fn test_swap_remove_existing_and_order() {
1259 let mut obj = Amf0Object::new();
1260
1261 obj.map.insert(StringCow::from("one"), Amf0Value::Number(1.0));
1262 obj.map.insert(StringCow::from("two"), Amf0Value::Number(2.0));
1263 obj.map.insert(StringCow::from("three"), Amf0Value::Number(3.0));
1264 obj.map.insert(StringCow::from("four"), Amf0Value::Number(4.0));
1265
1266 let removed = obj.swap_remove("two");
1267 assert_eq!(
1268 removed,
1269 Some(Amf0Value::Number(2.0)),
1270 "swap_remove should return the removed value for key 'two'"
1271 );
1272
1273 let keys_after: Vec<&str> = obj.map.keys().map(|k| k.as_ref()).collect();
1274 assert_eq!(
1275 keys_after,
1276 vec!["one", "four", "three"],
1277 "After swap_remove on 'two', order should be [\"one\", \"four\", \"three\"]"
1278 );
1279 assert!(!obj.map.contains_key("two"), "Key 'two' should no longer exist");
1280 assert!(obj.map.contains_key("four"), "Key 'four' should still be present");
1281 assert!(
1282 obj.swap_remove("absent").is_none(),
1283 "swap_remove on nonexistent key should return None"
1284 );
1285 }
1286
1287 #[test]
1288 #[cfg(feature = "preserve_order")]
1289 fn test_swap_remove_entry_preserve_order() {
1290 let mut obj = Amf0Object::new();
1291
1292 obj.map.insert(StringCow::from("a"), Amf0Value::Number(10.0));
1293 obj.map.insert(StringCow::from("b"), Amf0Value::Number(20.0));
1294 obj.map.insert(StringCow::from("c"), Amf0Value::Number(30.0));
1295 obj.map.insert(StringCow::from("d"), Amf0Value::Number(40.0));
1296
1297 let entry = obj.swap_remove_entry("b");
1298 assert_eq!(
1299 entry,
1300 Some((StringCow::from("b"), Amf0Value::Number(20.0))),
1301 "Expected swap_remove_entry to return the removed key 'b' and its value"
1302 );
1303
1304 let keys_after: Vec<&str> = obj.map.keys().map(|k| k.as_ref()).collect();
1305 assert_eq!(
1306 keys_after,
1307 vec!["a", "d", "c"],
1308 "After swap_remove_entry on 'b', order should be [\"a\", \"d\", \"c\"]"
1309 );
1310
1311 assert!(!obj.map.contains_key("b"), "Key 'b' should no longer exist");
1312 assert!(obj.map.contains_key("d"), "Key 'd' should still be present");
1313 assert!(obj.map.contains_key("c"), "Key 'c' should still be present");
1314 assert!(
1315 obj.swap_remove_entry("missing").is_none(),
1316 "swap_remove_entry on nonexistent key should return None"
1317 );
1318 }
1319
1320 #[test]
1321 #[cfg(feature = "preserve_order")]
1322 fn test_shift_remove_preserve_order() {
1323 let mut obj = Amf0Object::new();
1324
1325 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1326 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1327 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1328 obj.map.insert(StringCow::from("d"), Amf0Value::Number(4.0));
1329
1330 let removed = obj.shift_remove("b");
1331 assert_eq!(
1332 removed,
1333 Some(Amf0Value::Number(2.0)),
1334 "shift_remove should return the removed value for key 'b'"
1335 );
1336
1337 let keys_after: Vec<&str> = obj.map.keys().map(|k| k.as_ref()).collect();
1338 assert_eq!(
1339 keys_after,
1340 vec!["a", "c", "d"],
1341 "After shift_remove on 'b', order should be [\"a\", \"c\", \"d\"]"
1342 );
1343 assert!(!obj.map.contains_key("b"), "Key 'b' should no longer exist");
1344 assert!(obj.map.contains_key("c"), "Key 'c' should still be present");
1345 assert!(obj.map.contains_key("d"), "Key 'd' should still be present");
1346 assert!(
1347 obj.shift_remove("missing").is_none(),
1348 "shift_remove on nonexistent key should return None"
1349 );
1350 }
1351
1352 #[test]
1353 #[cfg(feature = "preserve_order")]
1354 fn test_shift_remove_entry_preserve_order() {
1355 let mut obj = Amf0Object::new();
1356
1357 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1358 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1359 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1360 obj.map.insert(StringCow::from("d"), Amf0Value::Number(4.0));
1361
1362 let entry = obj.shift_remove_entry("b");
1363 assert_eq!(
1364 entry,
1365 Some((StringCow::from("b"), Amf0Value::Number(2.0))),
1366 "Expected shift_remove_entry to return removed key 'b' and its value"
1367 );
1368
1369 let keys_after: Vec<&str> = obj.map.keys().map(|k| k.as_ref()).collect();
1370 assert_eq!(
1371 keys_after,
1372 vec!["a", "c", "d"],
1373 "After shift_remove_entry on 'b', order should be [\"a\", \"c\", \"d\"]"
1374 );
1375 assert!(!obj.map.contains_key("b"), "Key 'b' should no longer exist");
1376 assert!(obj.map.contains_key("c"), "Key 'c' should still be present");
1377 assert!(obj.map.contains_key("d"), "Key 'd' should still be present");
1378 assert!(
1379 obj.shift_remove_entry("missing").is_none(),
1380 "shift_remove_entry on nonexistent key should return None"
1381 );
1382 }
1383
1384 #[test]
1385 #[cfg(not(feature = "preserve_order"))]
1386 fn test_append_non_preserve_order_merges_and_clears_other() {
1387 let mut obj1 = Amf0Object::new();
1388 let mut obj2 = Amf0Object::new();
1389
1390 obj1.map.insert(StringCow::from("k1"), Amf0Value::Number(1.0));
1391 obj1.map.insert(StringCow::from("k2"), Amf0Value::Number(2.0));
1392
1393 obj2.map.insert(StringCow::from("k2"), Amf0Value::Number(22.0)); obj2.map.insert(StringCow::from("k3"), Amf0Value::Number(3.0));
1395 obj1.append(&mut obj2);
1396
1397 assert_eq!(obj1.map.len(), 3);
1398 assert_eq!(obj1.map.get("k1"), Some(&Amf0Value::Number(1.0)));
1399 assert_eq!(obj1.map.get("k2"), Some(&Amf0Value::Number(22.0)));
1400 assert_eq!(obj1.map.get("k3"), Some(&Amf0Value::Number(3.0)));
1401 assert!(obj2.map.is_empty(), "obj2 should be emptied after append");
1402 }
1403
1404 #[test]
1405 #[cfg(feature = "preserve_order")]
1406 fn test_append_preserve_order_extends_and_clears_other() {
1407 let mut obj1 = Amf0Object::new();
1408 let mut obj2 = Amf0Object::new();
1409
1410 obj1.map.insert(StringCow::from("a"), Amf0Value::Number(10.0));
1411 obj1.map.insert(StringCow::from("b"), Amf0Value::Number(20.0));
1412
1413 obj2.map.insert(StringCow::from("b"), Amf0Value::Number(200.0)); obj2.map.insert(StringCow::from("c"), Amf0Value::Number(30.0));
1415 obj1.append(&mut obj2);
1416
1417 let keys_after: Vec<&str> = obj1.map.keys().map(|k| k.as_ref()).collect();
1418 let values_after: Vec<&Amf0Value> = obj1.map.values().collect();
1419
1420 assert_eq!(
1421 keys_after,
1422 vec!["a", "b", "c"],
1423 "Order should preserve original keys, with duplicates replaced, then obj2's new keys"
1424 );
1425
1426 assert_eq!(
1427 values_after,
1428 vec![&Amf0Value::Number(10.0), &Amf0Value::Number(200.0), &Amf0Value::Number(30.0),]
1429 );
1430
1431 assert!(obj2.map.is_empty(), "obj2 should be emptied after append");
1432 }
1433
1434 #[test]
1435 #[cfg(not(feature = "preserve_order"))]
1436 fn test_entry_vacant_inserts_value_non_preserve_order() {
1437 let mut obj = Amf0Object::new();
1438
1439 match obj.entry("new_key") {
1440 Entry::Vacant(mut vacant) => {
1441 vacant.insert(Amf0Value::Number(42.0));
1442 }
1443 Entry::Occupied(_) => panic!("Expected Vacant for a missing key"),
1444 }
1445
1446 assert_eq!(
1447 obj.map.get("new_key"),
1448 Some(&Amf0Value::Number(42.0)),
1449 "Value inserted via entry should be retrievable"
1450 );
1451 }
1452
1453 #[test]
1454 #[cfg(feature = "preserve_order")]
1455 fn test_entry_vacant_inserts_value_preserve_order() {
1456 let mut obj = Amf0Object::new();
1457 match obj.entry("vacant_key") {
1458 Entry::Vacant(vacant) => {
1459 vacant.insert(Amf0Value::Number(123.0));
1460 }
1461 Entry::Occupied(_) => panic!("Expected Vacant for a missing key"),
1462 }
1463
1464 let keys: Vec<&str> = obj.map.keys().map(|k| k.as_ref()).collect();
1465 assert_eq!(keys, vec!["vacant_key"]);
1466 assert_eq!(obj.map.get("vacant_key"), Some(&Amf0Value::Number(123.0)));
1467 }
1468
1469 #[test]
1470 #[cfg(feature = "preserve_order")]
1471 fn test_entry_occupied_modifies_existing_value_preserve_order() {
1472 let mut obj = Amf0Object::new();
1473 obj.map.insert(StringCow::from("existing"), Amf0Value::Number(1.0));
1474
1475 match obj.entry("existing") {
1476 Entry::Vacant(_) => panic!("Expected Occupied for an existing key"),
1477 Entry::Occupied(mut occupied) => {
1478 *occupied.get_mut() = Amf0Value::Number(99.0);
1479 }
1480 }
1481
1482 assert_eq!(
1483 obj.map.get("existing"),
1484 Some(&Amf0Value::Number(99.0)),
1485 "Occupied entry modification should update the stored value"
1486 );
1487 }
1488
1489 #[test]
1490 #[cfg(not(feature = "preserve_order"))]
1491 fn test_is_empty_non_preserve_order() {
1492 let mut obj = Amf0Object::new();
1493 assert!(obj.is_empty(), "Newly created Amf0Object should be empty");
1494
1495 obj.map.insert(StringCow::from("key"), Amf0Value::Number(5.0));
1496 assert!(!obj.is_empty(), "Amf0Object should not be empty after insertion");
1497
1498 obj.clear();
1499 assert!(obj.is_empty(), "Amf0Object should be empty after clear");
1500 }
1501
1502 #[test]
1503 #[cfg(feature = "preserve_order")]
1504 fn test_is_empty_preserve_order() {
1505 let mut obj = Amf0Object::new();
1506 assert!(obj.is_empty(), "Newly created Amf0Object should be empty");
1507
1508 obj.map.insert(StringCow::from("alpha"), Amf0Value::Number(1.0));
1509 assert!(!obj.is_empty(), "Amf0Object should not be empty after insertion");
1510
1511 obj.shift_remove("alpha");
1512 assert!(obj.is_empty(), "Amf0Object should be empty after removing the only key");
1513 }
1514
1515 #[test]
1516 #[cfg(not(feature = "preserve_order"))]
1517 fn test_iter_mut_non_preserve_order() {
1518 let mut obj = Amf0Object::new();
1519 obj.map.insert(StringCow::from("k1"), Amf0Value::Number(1.0));
1520 obj.map.insert(StringCow::from("k2"), Amf0Value::Number(2.0));
1521 obj.map.insert(StringCow::from("k3"), Amf0Value::Number(3.0));
1522
1523 for (_k, v) in obj.iter_mut() {
1524 if let Amf0Value::Number(ref mut n) = *v {
1525 *n += 10.0;
1526 }
1527 }
1528
1529 assert_eq!(obj.map.get("k1"), Some(&Amf0Value::Number(11.0)));
1530 assert_eq!(obj.map.get("k2"), Some(&Amf0Value::Number(12.0)));
1531 assert_eq!(obj.map.get("k3"), Some(&Amf0Value::Number(13.0)));
1532 }
1533
1534 #[test]
1535 #[cfg(feature = "preserve_order")]
1536 fn test_iter_mut_preserve_order() {
1537 let mut obj = Amf0Object::new();
1538 obj.map.insert(StringCow::from("a"), Amf0Value::Number(5.0));
1539 obj.map.insert(StringCow::from("b"), Amf0Value::Number(6.0));
1540 obj.map.insert(StringCow::from("c"), Amf0Value::Number(7.0));
1541
1542 let keys: Vec<&str> = obj.iter_mut().map(|(k, _)| k.as_ref()).collect();
1543 assert_eq!(keys, vec!["a", "b", "c"], "Iteration order should follow insertion order");
1544
1545 for (_k, v) in obj.iter_mut() {
1546 *v = Amf0Value::Number(0.0);
1547 }
1548
1549 assert_eq!(obj.map.get("a"), Some(&Amf0Value::Number(0.0)));
1550 assert_eq!(obj.map.get("b"), Some(&Amf0Value::Number(0.0)));
1551 assert_eq!(obj.map.get("c"), Some(&Amf0Value::Number(0.0)));
1552 }
1553
1554 #[test]
1555 #[cfg(not(feature = "preserve_order"))]
1556 fn test_keys_non_preserve_order_sorted() {
1557 let mut obj = Amf0Object::new();
1558
1559 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1560 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1561 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1562
1563 let keys: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
1564 assert_eq!(keys, vec!["a", "b", "c"], "Expected keys sorted lexicographically");
1565 }
1566
1567 #[test]
1568 #[cfg(feature = "preserve_order")]
1569 fn test_keys_preserve_order_insertion() {
1570 let mut obj = Amf0Object::new();
1571
1572 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1573 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1574 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1575
1576 let keys: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
1577 assert_eq!(keys, vec!["b", "a", "c"], "Expected keys in insertion order");
1578 }
1579
1580 #[test]
1581 #[cfg(not(feature = "preserve_order"))]
1582 fn test_values_non_preserve_order_sorted_by_key() {
1583 let mut obj = Amf0Object::new();
1584
1585 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1586 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1587 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1588
1589 let values: Vec<&Amf0Value> = obj.values().collect();
1590 assert_eq!(
1591 values,
1592 vec![&Amf0Value::Number(1.0), &Amf0Value::Number(2.0), &Amf0Value::Number(3.0)],
1593 "Expected values in order of sorted keys"
1594 );
1595 }
1596
1597 #[test]
1598 #[cfg(feature = "preserve_order")]
1599 fn test_values_preserve_order_insertion() {
1600 let mut obj = Amf0Object::new();
1601
1602 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1603 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1604 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1605
1606 let values: Vec<&Amf0Value> = obj.values().collect();
1607 assert_eq!(
1608 values,
1609 vec![&Amf0Value::Number(2.0), &Amf0Value::Number(1.0), &Amf0Value::Number(3.0)],
1610 "Expected values in insertion order"
1611 );
1612 }
1613
1614 #[test]
1615 #[cfg(not(feature = "preserve_order"))]
1616 fn test_values_mut_non_preserve_order() {
1617 let mut obj = Amf0Object::new();
1618
1619 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1620 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1621 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1622
1623 for value in obj.values_mut() {
1624 if let Amf0Value::Number(ref mut n) = *value {
1625 *n *= 10.0;
1626 }
1627 }
1628
1629 let sorted_keys: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
1630 assert_eq!(sorted_keys, vec!["a", "b", "c"]);
1631
1632 assert_eq!(obj.map.get("a"), Some(&Amf0Value::Number(10.0)));
1633 assert_eq!(obj.map.get("b"), Some(&Amf0Value::Number(20.0)));
1634 assert_eq!(obj.map.get("c"), Some(&Amf0Value::Number(30.0)));
1635 }
1636
1637 #[test]
1638 #[cfg(feature = "preserve_order")]
1639 fn test_values_mut_preserve_order() {
1640 let mut obj = Amf0Object::new();
1641
1642 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1643 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1644 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1645
1646 for value in obj.values_mut() {
1647 *value = Amf0Value::Number(0.0);
1648 }
1649
1650 let keys_in_order: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
1651 assert_eq!(keys_in_order, vec!["b", "a", "c"]);
1652
1653 assert_eq!(obj.map.get("b"), Some(&Amf0Value::Number(0.0)));
1654 assert_eq!(obj.map.get("a"), Some(&Amf0Value::Number(0.0)));
1655 assert_eq!(obj.map.get("c"), Some(&Amf0Value::Number(0.0)));
1656 }
1657
1658 #[test]
1659 #[cfg(not(feature = "preserve_order"))]
1660 fn test_into_values_consume_and_return_sorted_values() {
1661 let mut obj = Amf0Object::new();
1662
1663 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1664 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1665 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1666
1667 let values: Vec<Amf0Value> = obj.into_values().collect();
1668 assert_eq!(
1669 values,
1670 vec![Amf0Value::Number(1.0), Amf0Value::Number(2.0), Amf0Value::Number(3.0)],
1671 "into_values should yield values in key‐sorted order for BTreeMap"
1672 );
1673 }
1674
1675 #[test]
1676 #[cfg(feature = "preserve_order")]
1677 fn test_into_values_consume_and_return_insertion_order_values() {
1678 let mut obj = Amf0Object::new();
1679
1680 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1681 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1682 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1683
1684 let values: Vec<Amf0Value> = obj.into_values().collect();
1685 assert_eq!(
1686 values,
1687 vec![Amf0Value::Number(2.0), Amf0Value::Number(1.0), Amf0Value::Number(3.0)],
1688 "into_values should yield values in insertion order for IndexMap"
1689 );
1690 }
1691
1692 #[test]
1693 #[cfg(not(feature = "preserve_order"))]
1694 fn test_retain_non_preserve_order() {
1695 let mut obj = Amf0Object::new();
1696
1697 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1698 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1699 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1700 obj.map.insert(StringCow::from("d"), Amf0Value::Number(4.0));
1701
1702 obj.retain(|_key, value| if let Amf0Value::Number(n) = *value { n > 2.0 } else { false });
1703
1704 let remaining_keys: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
1705 assert_eq!(remaining_keys, vec!["c", "d"]);
1706
1707 assert_eq!(obj.map.get("c"), Some(&Amf0Value::Number(3.0)));
1708 assert_eq!(obj.map.get("d"), Some(&Amf0Value::Number(4.0)));
1709
1710 assert!(!obj.map.contains_key("a"));
1711 assert!(!obj.map.contains_key("b"));
1712 }
1713
1714 #[test]
1715 #[cfg(feature = "preserve_order")]
1716 fn test_retain_preserve_order() {
1717 let mut obj = Amf0Object::new();
1718
1719 obj.map.insert(StringCow::from("x1"), Amf0Value::Number(1.0));
1720 obj.map.insert(StringCow::from("x2"), Amf0Value::Number(2.0));
1721 obj.map.insert(StringCow::from("x3"), Amf0Value::Number(3.0));
1722 obj.map.insert(StringCow::from("x4"), Amf0Value::Number(4.0));
1723
1724 obj.retain(|_key, value| {
1725 if let Amf0Value::Number(n) = *value {
1726 (n as i64) % 2 == 0
1727 } else {
1728 false
1729 }
1730 });
1731
1732 let remaining_keys: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
1733 assert_eq!(remaining_keys, vec!["x2", "x4"]);
1734
1735 assert_eq!(obj.map.get("x2"), Some(&Amf0Value::Number(2.0)));
1736 assert_eq!(obj.map.get("x4"), Some(&Amf0Value::Number(4.0)));
1737
1738 assert!(!obj.map.contains_key("x1"));
1739 assert!(!obj.map.contains_key("x3"));
1740 }
1741
1742 #[test]
1743 #[cfg(feature = "preserve_order")]
1744 fn test_sort_keys_preserve_order() {
1745 let mut obj = Amf0Object::new();
1746
1747 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1748 obj.map.insert(StringCow::from("d"), Amf0Value::Number(4.0));
1749 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1750 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1751
1752 let before: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
1753 assert_eq!(before, vec!["b", "d", "a", "c"]);
1754
1755 obj.sort_keys();
1756
1757 let after: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
1758 assert_eq!(after, vec!["a", "b", "c", "d"]);
1759
1760 assert_eq!(obj.map.get("a"), Some(&Amf0Value::Number(1.0)));
1761 assert_eq!(obj.map.get("b"), Some(&Amf0Value::Number(2.0)));
1762 assert_eq!(obj.map.get("c"), Some(&Amf0Value::Number(3.0)));
1763 assert_eq!(obj.map.get("d"), Some(&Amf0Value::Number(4.0)));
1764 }
1765
1766 #[test]
1767 fn test_index_returns_value_for_existing_key() {
1768 let mut obj = Amf0Object::new();
1769 obj.map.insert(StringCow::from("alpha"), Amf0Value::Number(3.21));
1770
1771 let v: &Amf0Value = &obj["alpha"];
1772 assert_eq!(v, &Amf0Value::Number(3.21));
1773 }
1774
1775 #[test]
1776 #[should_panic]
1777 fn test_index_panics_on_missing_key() {
1778 let obj = Amf0Object::new();
1779 let _ = &obj["nonexistent"];
1781 }
1782
1783 #[test]
1784 fn test_index_mut_modifies_existing_value() {
1785 let mut obj = Amf0Object::new();
1786 obj.map.insert(StringCow::from("key1"), Amf0Value::Number(5.0));
1787
1788 obj["key1"] = Amf0Value::Number(42.0);
1789
1790 assert_eq!(
1791 obj.map.get("key1"),
1792 Some(&Amf0Value::Number(42.0)),
1793 "IndexMut should allow updating the value"
1794 );
1795 }
1796
1797 #[test]
1798 #[should_panic(expected = "no entry found for key")]
1799 fn test_index_mut_panics_on_missing_key() {
1800 let mut obj = Amf0Object::new();
1801 obj["nonexistent"] = Amf0Value::Boolean(true);
1802 }
1803
1804 #[cfg(not(feature = "preserve_order"))]
1805 #[test]
1806 fn test_debug_formats_sorted_map_non_preserve_order() {
1807 let mut obj = Amf0Object::new();
1808
1809 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1810 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1811
1812 insta::assert_debug_snapshot!(obj, @r#"
1813 {
1814 Ref(
1815 "b",
1816 ): Number(
1817 2.0,
1818 ),
1819 Ref(
1820 "a",
1821 ): Number(
1822 1.0,
1823 ),
1824 }
1825 "#);
1826 }
1827
1828 #[cfg(feature = "preserve_order")]
1829 #[test]
1830 fn test_debug_formats_insertion_order_preserve_order() {
1831 let mut obj = Amf0Object::new();
1832
1833 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1834 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1835
1836 insta::assert_debug_snapshot!(obj, @r#"
1837 {
1838 Ref(
1839 "b",
1840 ): Number(
1841 2.0,
1842 ),
1843 Ref(
1844 "a",
1845 ): Number(
1846 1.0,
1847 ),
1848 }
1849 "#);
1850 }
1851
1852 #[cfg(feature = "serde")]
1853 #[test]
1854 fn test_visit_unit_returns_empty_object() {
1855 use serde::de::value::{Error as DeError, UnitDeserializer};
1856
1857 let deser: UnitDeserializer<DeError> = UnitDeserializer::new();
1859 let obj = Amf0Object::deserialize(deser).unwrap();
1860
1861 assert!(obj.is_empty(), "visit_unit should produce an empty Amf0Object");
1862 }
1863
1864 #[cfg(feature = "serde")]
1865 #[test]
1866 fn test_expecting_error_message() {
1867 use serde::de::value::Error as DeError;
1868 use serde::de::{self};
1869
1870 struct WrongTypeDeserializer;
1871
1872 impl<'de> de::Deserializer<'de> for WrongTypeDeserializer {
1873 type Error = DeError;
1874
1875 serde::forward_to_deserialize_any! {
1876 bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes byte_buf
1877 option unit unit_struct newtype_struct seq tuple tuple_struct map struct
1878 enum identifier ignored_any
1879 }
1880
1881 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
1882 where
1883 V: de::Visitor<'de>,
1884 {
1885 Err(de::Error::invalid_type(de::Unexpected::Bool(true), &visitor))
1886 }
1887 }
1888
1889 let err = Amf0Object::deserialize(WrongTypeDeserializer).unwrap_err();
1890 let msg = err.to_string();
1891
1892 assert!(
1893 msg.contains("a map"),
1894 "expecting() should include 'a map' in the error message, got: '{}'",
1895 msg
1896 );
1897 }
1898
1899 #[cfg(not(feature = "preserve_order"))]
1900 #[test]
1901 fn test_extend_non_preserve_order_inserts_and_sorts() {
1902 let mut obj = Amf0Object::new();
1903
1904 let items = vec![
1905 (StringCow::from("b"), Amf0Value::Number(2.0)),
1906 (StringCow::from("a"), Amf0Value::Number(1.0)),
1907 (StringCow::from("a"), Amf0Value::Number(5.0)),
1908 (StringCow::from("c"), Amf0Value::Number(3.0)),
1909 ];
1910
1911 obj.extend(items);
1912
1913 let keys: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
1914 assert_eq!(
1915 keys,
1916 vec!["a", "b", "c"],
1917 "Non-preserve_order: keys should be sorted lexicographically"
1918 );
1919
1920 assert_eq!(obj.map.get("a"), Some(&Amf0Value::Number(5.0)));
1921 assert_eq!(obj.map.get("b"), Some(&Amf0Value::Number(2.0)));
1922 assert_eq!(obj.map.get("c"), Some(&Amf0Value::Number(3.0)));
1923 }
1924
1925 #[cfg(feature = "preserve_order")]
1926 #[test]
1927 fn test_extend_preserve_order_inserts_and_overwrites() {
1928 let mut obj = Amf0Object::new();
1929
1930 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1931
1932 let items = vec![
1933 (StringCow::from("a"), Amf0Value::Number(5.0)),
1934 (StringCow::from("b"), Amf0Value::Number(2.0)),
1935 (StringCow::from("a"), Amf0Value::Number(7.0)),
1936 (StringCow::from("c"), Amf0Value::Number(3.0)),
1937 ];
1938
1939 obj.extend(items);
1940
1941 let keys: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
1942 assert_eq!(
1943 keys,
1944 vec!["a", "b", "c"],
1945 "Preserve_order: key 'a' remains at front, then 'b', then 'c'"
1946 );
1947
1948 assert_eq!(obj.map.get("a"), Some(&Amf0Value::Number(7.0)));
1949 assert_eq!(obj.map.get("b"), Some(&Amf0Value::Number(2.0)));
1950 assert_eq!(obj.map.get("c"), Some(&Amf0Value::Number(3.0)));
1951 }
1952
1953 #[cfg(not(feature = "preserve_order"))]
1954 #[test]
1955 fn test_keys_iterator_next_back_and_len_non_preserve_order() {
1956 let mut obj = Amf0Object::new();
1957
1958 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1959 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1960 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1961
1962 let mut keys_iter = obj.keys();
1963
1964 assert_eq!(keys_iter.len(), 3);
1965
1966 let last = keys_iter.next_back().expect("Expected a last key");
1967 assert_eq!(last.as_ref(), "c");
1968
1969 assert_eq!(keys_iter.len(), 2);
1970
1971 let first = keys_iter.next().expect("Expected a first key");
1972 assert_eq!(first.as_ref(), "a");
1973
1974 assert_eq!(keys_iter.len(), 1);
1975 }
1976
1977 #[cfg(feature = "preserve_order")]
1978 #[test]
1979 fn test_keys_iterator_next_back_and_len_preserve_order() {
1980 let mut obj = Amf0Object::new();
1981
1982 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
1983 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
1984 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
1985
1986 let mut keys_iter = obj.keys();
1987
1988 assert_eq!(keys_iter.len(), 3);
1989
1990 let last = keys_iter.next_back().expect("Expected a last key");
1991 assert_eq!(last.as_ref(), "c");
1992
1993 assert_eq!(keys_iter.len(), 2);
1994
1995 let first = keys_iter.next().expect("Expected a first key");
1996 assert_eq!(first.as_ref(), "b");
1997 assert_eq!(keys_iter.len(), 1);
1998 }
1999
2000 #[cfg(feature = "serde")]
2001 #[test]
2002 fn test_into_deserializer_returns_self() {
2003 use serde::de::IntoDeserializer;
2004
2005 use crate::Amf0Error;
2006
2007 let obj = Amf0Object::new();
2008
2009 let deser: &Amf0Object = <&Amf0Object as IntoDeserializer<Amf0Error>>::into_deserializer(&obj);
2010 assert!(
2011 std::ptr::eq(deser, &obj),
2012 "into_deserializer should return the exact same &Amf0Object reference"
2013 );
2014 }
2015
2016 #[cfg(feature = "serde")]
2017 #[test]
2018 fn test_into_deserializer_as_deserializer_errors_on_primitive() {
2019 use serde::Deserialize;
2020 use serde::de::IntoDeserializer;
2021
2022 let obj = Amf0Object::new();
2023 let deser = obj.into_deserializer();
2024
2025 let result = <bool as Deserialize>::deserialize(&deser);
2026 assert!(result.is_err(), "Deserializing a bool from an Amf0Object should error");
2027 }
2028
2029 #[derive(Debug, Deserialize, PartialEq)]
2030 struct TestObject {
2031 string: String,
2032 number: u32,
2033 }
2034
2035 #[cfg(feature = "serde")]
2036 #[test]
2037 fn test_deserialize_any_for_struct() {
2038 let mut obj = Amf0Object::new();
2039 obj.map
2040 .insert(StringCow::from("string"), Amf0Value::String(StringCow::from("apple")));
2041 obj.map.insert(StringCow::from("number"), Amf0Value::Number(30.0));
2042
2043 let testobj: TestObject = Deserialize::deserialize(&obj).unwrap();
2044 assert_eq!(
2045 testobj,
2046 TestObject {
2047 string: "apple".into(),
2048 number: 30,
2049 }
2050 );
2051 }
2052
2053 #[cfg(feature = "serde")]
2054 #[test]
2055 fn test_deserialize_any_errors_on_missing_field() {
2056 let mut obj = Amf0Object::new();
2057 obj.map
2058 .insert(StringCow::from("string"), Amf0Value::String(StringCow::from("banana")));
2059
2060 let result: Result<TestObject, _> = Deserialize::deserialize(&obj);
2061 assert!(result.is_err(), "Missing required field should cause an error");
2062 }
2063
2064 #[test]
2065 fn test_entry_key_occupied() {
2066 let mut obj = Amf0Object::new();
2067 obj.map.insert(StringCow::from("serde"), Amf0Value::Number(42.0));
2068 let entry = obj.entry("serde");
2069
2070 assert_eq!(entry.key(), &StringCow::from("serde"));
2071 }
2072
2073 #[test]
2074 fn test_or_insert_vacant_and_occupied() {
2075 let mut obj = Amf0Object::new();
2076
2077 let v = obj.entry("k").or_insert(Amf0Value::Number(10.0));
2078 assert_eq!(*v, Amf0Value::Number(10.0));
2079 assert_eq!(
2080 obj.map.get("k"),
2081 Some(&Amf0Value::Number(10.0)),
2082 "Value should be inserted for vacant entry"
2083 );
2084
2085 let v2 = obj.entry("k").or_insert(Amf0Value::Number(20.0));
2086 assert_eq!(*v2, Amf0Value::Number(10.0));
2087
2088 *v2 = Amf0Value::Number(30.0);
2089 assert_eq!(
2090 obj.map.get("k"),
2091 Some(&Amf0Value::Number(30.0)),
2092 "Value should be updated to 30.0 via the occupied branch"
2093 );
2094 }
2095
2096 #[test]
2097 fn test_or_insert_with_vacant_and_occupied() {
2098 use std::cell::Cell;
2099
2100 let mut obj = Amf0Object::new();
2101
2102 let called = Cell::new(false);
2103 let default_closure = || {
2104 called.set(true);
2105 Amf0Value::Number(5.0)
2106 };
2107
2108 let v = obj.entry("key1").or_insert_with(default_closure);
2109 assert!(called.get(), "Closure should have been called for vacant entry");
2110 assert_eq!(*v, Amf0Value::Number(5.0));
2111 assert_eq!(
2112 obj.map.get("key1"),
2113 Some(&Amf0Value::Number(5.0)),
2114 "Value for 'key1' should be inserted as 5.0"
2115 );
2116
2117 called.set(false);
2118 let v2 = obj.entry("key1").or_insert_with(|| {
2119 called.set(true);
2120 Amf0Value::Number(10.0)
2121 });
2122 assert!(!called.get(), "Closure should not be called for occupied entry");
2123 assert_eq!(*v2, Amf0Value::Number(5.0));
2124
2125 *v2 = Amf0Value::Number(7.0);
2126 assert_eq!(
2127 obj.map.get("key1"),
2128 Some(&Amf0Value::Number(7.0)),
2129 "Value for 'key1' should be updated to 7.0 via occupied branch"
2130 );
2131 }
2132
2133 #[test]
2134 fn test_and_modify_on_occupied_entry() {
2135 let mut obj = Amf0Object::new();
2136 obj.map.insert(StringCow::from("key1"), Amf0Value::Number(1.0));
2137
2138 obj.entry("key1").and_modify(|v| {
2139 if let Amf0Value::Number(n) = v {
2140 *n = 5.0;
2141 }
2142 });
2143
2144 assert_eq!(
2145 obj.map.get("key1"),
2146 Some(&Amf0Value::Number(5.0)),
2147 "and_modify should change the existing value from 1.0 to 5.0"
2148 );
2149 }
2150
2151 #[test]
2152 fn test_and_modify_on_vacant_entry() {
2153 let mut obj = Amf0Object::new();
2154 assert!(!obj.map.contains_key("missing"));
2155
2156 obj.entry("missing").and_modify(|v| {
2157 if let Amf0Value::Number(n) = v {
2158 *n = 100.0;
2159 }
2160 });
2161
2162 assert!(
2163 !obj.map.contains_key("missing"),
2164 "and_modify on a vacant entry should not insert anything"
2165 );
2166 }
2167
2168 #[test]
2169 fn test_occupied_entry_key_and_get() {
2170 let mut obj = Amf0Object::new();
2171
2172 obj.map.insert(StringCow::from("my_key"), Amf0Value::Number(123.0));
2173
2174 match obj.entry("my_key") {
2175 Entry::Occupied(occupied) => {
2176 let key_ref: &StringCow = occupied.key();
2177 assert_eq!(key_ref.as_ref(), "my_key");
2178
2179 let value_ref: &Amf0Value = occupied.get();
2180 assert_eq!(value_ref, &Amf0Value::Number(123.0));
2181 }
2182 Entry::Vacant(_) => panic!("Expected Occupied variant for an existing key"),
2183 }
2184 }
2185
2186 #[test]
2187 fn test_occupied_entry_into_mut_and_insert() {
2188 let mut obj = Amf0Object::new();
2189
2190 obj.map.insert(StringCow::from("key1"), Amf0Value::Number(10.0));
2191
2192 if let Entry::Occupied(occ) = obj.entry("key1") {
2193 let value_ref: &mut Amf0Value = occ.into_mut();
2194 if let Amf0Value::Number(n) = value_ref {
2195 *n = 20.0;
2196 }
2197 } else {
2198 panic!("Expected Occupied variant");
2199 }
2200
2201 assert_eq!(
2202 obj.map.get("key1"),
2203 Some(&Amf0Value::Number(20.0)),
2204 "into_mut should allow modifying the existing value"
2205 );
2206
2207 if let Entry::Occupied(mut occ2) = obj.entry("key1") {
2208 let old = occ2.insert(Amf0Value::Number(30.0));
2209 assert_eq!(old, Amf0Value::Number(20.0), "insert should return the old value");
2210 } else {
2211 panic!("Expected Occupied variant for insert test");
2212 }
2213
2214 assert_eq!(
2215 obj.map.get("key1"),
2216 Some(&Amf0Value::Number(30.0)),
2217 "insert should replace with the new value"
2218 );
2219 }
2220
2221 #[cfg(not(feature = "preserve_order"))]
2222 #[test]
2223 fn test_occupied_entry_remove_non_preserve_order() {
2224 let mut obj = Amf0Object::new();
2225
2226 obj.map.insert(StringCow::from("key1"), Amf0Value::Number(1.0));
2227
2228 if let Entry::Occupied(occ) = obj.entry("key1") {
2229 let removed_value = occ.remove();
2230 assert_eq!(removed_value, Amf0Value::Number(1.0), "remove should return the old value");
2231 } else {
2232 panic!("Expected Occupied variant");
2233 }
2234
2235 assert!(!obj.map.contains_key("key1"), "Key should be removed after calling remove()");
2236 }
2237
2238 #[cfg(feature = "preserve_order")]
2239 #[test]
2240 fn test_occupied_entry_remove_preserve_order() {
2241 let mut obj = Amf0Object::new();
2242
2243 obj.map.insert(StringCow::from("a"), Amf0Value::Number(10.0));
2244 obj.map.insert(StringCow::from("b"), Amf0Value::Number(20.0));
2245 obj.map.insert(StringCow::from("c"), Amf0Value::Number(30.0));
2246
2247 if let Entry::Occupied(occ) = obj.entry("b") {
2248 let removed_value = occ.remove();
2249 assert_eq!(removed_value, Amf0Value::Number(20.0), "remove should return the old value");
2250 } else {
2251 panic!("Expected Occupied variant");
2252 }
2253
2254 let keys_after: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
2255 assert_eq!(
2256 keys_after,
2257 vec!["a", "c"],
2258 "After remove, key 'b' should be gone and 'c' should occupy its position"
2259 );
2260 assert!(!obj.map.contains_key("b"), "Key 'b' should be removed");
2261 }
2262
2263 #[cfg(feature = "preserve_order")]
2264 #[test]
2265 fn test_occupied_entry_swap_remove_preserve_order() {
2266 let mut obj = Amf0Object::new();
2267
2268 obj.map.insert(StringCow::from("x"), Amf0Value::Number(1.0));
2269 obj.map.insert(StringCow::from("y"), Amf0Value::Number(2.0));
2270 obj.map.insert(StringCow::from("z"), Amf0Value::Number(3.0));
2271
2272 if let Entry::Occupied(occ) = obj.entry("y") {
2273 let removed = occ.swap_remove();
2274 assert_eq!(
2275 removed,
2276 Amf0Value::Number(2.0),
2277 "swap_remove should return the old value for 'y'"
2278 );
2279 } else {
2280 panic!("Expected Occupied variant for key 'y'");
2281 }
2282
2283 let keys_after: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
2284 assert_eq!(
2285 keys_after,
2286 vec!["x", "z"],
2287 "After swap_remove, 'y' should be gone and 'z' should occupy its slot"
2288 );
2289 assert!(!obj.map.contains_key("y"), "Key 'y' should be removed");
2290 assert!(obj.map.contains_key("z"), "Key 'z' should still be present");
2291 }
2292
2293 #[cfg(feature = "preserve_order")]
2294 #[test]
2295 fn test_occupied_entry_shift_remove_preserve_order() {
2296 let mut obj = Amf0Object::new();
2297
2298 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
2299 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
2300 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
2301 obj.map.insert(StringCow::from("d"), Amf0Value::Number(4.0));
2302
2303 if let Entry::Occupied(occ) = obj.entry("b") {
2304 let removed = occ.shift_remove();
2305 assert_eq!(
2306 removed,
2307 Amf0Value::Number(2.0),
2308 "shift_remove should return the old value for 'b'"
2309 );
2310 } else {
2311 panic!("Expected Occupied variant for key 'b'");
2312 }
2313
2314 let keys_after: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
2315 assert_eq!(
2316 keys_after,
2317 vec!["a", "c", "d"],
2318 "After shift_remove, 'b' should be gone and order should be [\"a\", \"c\", \"d\"]"
2319 );
2320 assert!(!obj.map.contains_key("b"), "Key 'b' should have been removed");
2321 assert!(obj.map.contains_key("c"), "Key 'c' should still be present");
2322 assert!(obj.map.contains_key("d"), "Key 'd' should still be present");
2323 }
2324
2325 #[cfg(not(feature = "preserve_order"))]
2326 #[test]
2327 fn test_occupied_entry_remove_entry_non_preserve_order() {
2328 let mut obj = Amf0Object::new();
2329
2330 obj.map.insert(StringCow::from("key1"), Amf0Value::Number(10.0));
2331
2332 if let Entry::Occupied(occ) = obj.entry("key1") {
2333 let (removed_key, removed_value) = occ.remove_entry();
2334 assert_eq!(removed_key, StringCow::from("key1"));
2335 assert_eq!(removed_value, Amf0Value::Number(10.0));
2336 } else {
2337 panic!("Expected Occupied variant for 'key1'");
2338 }
2339
2340 assert!(!obj.map.contains_key("key1"));
2341 }
2342
2343 #[cfg(feature = "preserve_order")]
2344 #[test]
2345 fn test_occupied_entry_remove_entry_preserve_order() {
2346 let mut obj = Amf0Object::new();
2347
2348 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
2349 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
2350 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
2351
2352 if let Entry::Occupied(occ) = obj.entry("b") {
2353 let (removed_key, removed_value) = occ.remove_entry();
2354 assert_eq!(removed_key, StringCow::from("b"));
2355 assert_eq!(removed_value, Amf0Value::Number(2.0));
2356 } else {
2357 panic!("Expected Occupied variant for 'b'");
2358 }
2359
2360 let remaining_keys: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
2361 assert_eq!(
2362 remaining_keys,
2363 vec!["a", "c"],
2364 "After remove_entry on 'b', keys should be [\"a\", \"c\"]"
2365 );
2366 assert!(!obj.map.contains_key("b"), "Key 'b' should be gone");
2367 assert!(obj.map.contains_key("c"), "Key 'c' should still be present");
2368 }
2369
2370 #[cfg(feature = "preserve_order")]
2371 #[test]
2372 fn test_swap_remove_entry_preserve_order_occupied_entry() {
2373 let mut obj = Amf0Object::new();
2374
2375 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
2377 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
2378 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
2379 obj.map.insert(StringCow::from("d"), Amf0Value::Number(4.0));
2380
2381 if let Entry::Occupied(occ) = obj.entry("b") {
2383 let (removed_key, removed_value) = occ.swap_remove_entry();
2384 assert_eq!(removed_key, StringCow::from("b"));
2385 assert_eq!(removed_value, Amf0Value::Number(2.0));
2386 } else {
2387 panic!("Expected Occupied variant for key 'b'");
2388 }
2389
2390 let remaining_keys: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
2392 assert_eq!(
2393 remaining_keys,
2394 vec!["a", "d", "c"],
2395 "After swap_remove_entry on 'b', keys should be [\"a\", \"d\", \"c\"]"
2396 );
2397 assert!(!obj.map.contains_key("b"), "Key 'b' should have been removed");
2398 assert!(obj.map.contains_key("d"), "Key 'd' should still be present");
2399 assert!(obj.map.contains_key("c"), "Key 'c' should still be present");
2400 }
2401
2402 #[test]
2403 #[cfg(feature = "preserve_order")]
2404 fn test_occupied_entry_shift_remove_entry_preserve_order() {
2405 let mut obj = Amf0Object::new();
2406
2407 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
2408 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
2409 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
2410 obj.map.insert(StringCow::from("d"), Amf0Value::Number(4.0));
2411
2412 if let Entry::Occupied(occ) = obj.entry("b") {
2413 let (removed_key, removed_value) = occ.shift_remove_entry();
2414 assert_eq!(
2415 removed_key,
2416 StringCow::from("b"),
2417 "shift_remove_entry should return the removed key 'b'"
2418 );
2419 assert_eq!(
2420 removed_value,
2421 Amf0Value::Number(2.0),
2422 "shift_remove_entry should return the correct value for 'b'"
2423 );
2424 } else {
2425 panic!("Expected Occupied variant for key 'b'");
2426 }
2427
2428 let remaining_keys: Vec<&str> = obj.keys().map(|k| k.as_ref()).collect();
2429 assert_eq!(
2430 remaining_keys,
2431 vec!["a", "c", "d"],
2432 "After shift_remove_entry on 'b', keys should be [\"a\", \"c\", \"d\"]"
2433 );
2434 assert!(!obj.map.contains_key("b"), "Key 'b' should have been removed");
2435 assert!(obj.map.contains_key("c"), "Key 'c' should still be present");
2436 assert!(obj.map.contains_key("d"), "Key 'd' should still be present");
2437 }
2438
2439 #[test]
2440 fn test_into_iterator_mutates_values_non_preserve_order() {
2441 let mut obj = Amf0Object::new();
2442
2443 obj.map.insert(StringCow::from("b"), Amf0Value::Number(2.0));
2444 obj.map.insert(StringCow::from("a"), Amf0Value::Number(1.0));
2445 obj.map.insert(StringCow::from("c"), Amf0Value::Number(3.0));
2446
2447 for (_, value) in &mut obj {
2448 if let Amf0Value::Number(n) = value {
2449 *n += 10.0;
2450 }
2451 }
2452
2453 assert_eq!(obj.map.get("a"), Some(&Amf0Value::Number(11.0)));
2454 assert_eq!(obj.map.get("b"), Some(&Amf0Value::Number(12.0)));
2455 assert_eq!(obj.map.get("c"), Some(&Amf0Value::Number(13.0)));
2456 }
2457
2458 #[test]
2459 #[cfg(feature = "preserve_order")]
2460 fn test_into_iterator_preserve_order_counts_and_mutates() {
2461 let mut obj = Amf0Object::new();
2462
2463 obj.map.insert(StringCow::from("x"), Amf0Value::Number(5.0));
2464 obj.map.insert(StringCow::from("y"), Amf0Value::Number(6.0));
2465 obj.map.insert(StringCow::from("z"), Amf0Value::Number(7.0));
2466
2467 let mut seen_keys = Vec::new();
2468 for (key, value) in &mut obj {
2469 seen_keys.push(key.as_ref().to_string());
2470 *value = Amf0Value::Number(0.0);
2471 }
2472
2473 assert_eq!(seen_keys, vec!["x", "y", "z"]);
2474 assert_eq!(obj.map.get("x"), Some(&Amf0Value::Number(0.0)));
2475 assert_eq!(obj.map.get("y"), Some(&Amf0Value::Number(0.0)));
2476 assert_eq!(obj.map.get("z"), Some(&Amf0Value::Number(0.0)));
2477 }
2478}