1use core::{borrow::Borrow, fmt, ops::ControlFlow};
14
15use crate::{
16 and::And,
17 empty::Empty,
18 str::{Str, ToStr},
19 value::{FromValue, ToValue, Value},
20};
21
22pub trait Props {
36 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
44 &'kv self,
45 for_each: F,
46 ) -> ControlFlow<()>;
47
48 fn get<'v, K: ToStr>(&'v self, key: K) -> Option<Value<'v>> {
58 let key = key.to_str();
59 let mut value = None;
60
61 let _ = self.for_each(|k, v| {
62 if k == key {
63 value = Some(v);
64
65 ControlFlow::Break(())
66 } else {
67 ControlFlow::Continue(())
68 }
69 });
70
71 value
72 }
73
74 fn pull<'kv, V: FromValue<'kv>, K: ToStr>(&'kv self, key: K) -> Option<V> {
82 self.get(key).and_then(|v| v.cast())
83 }
84
85 fn and_props<U: Props>(self, other: U) -> And<Self, U>
89 where
90 Self: Sized,
91 {
92 And::new(self, other)
93 }
94
95 fn filter<F: Fn(Str, Value) -> bool>(self, filter: F) -> Filter<Self, F>
101 where
102 Self: Sized,
103 {
104 Filter::new(self, filter)
105 }
106
107 fn collect<'kv, C: FromProps<'kv>>(&'kv self) -> C {
113 C::from_props(self)
114 }
115
116 fn as_map(&self) -> &AsMap<Self>
120 where
121 Self: Sized,
122 {
123 AsMap::new(self)
124 }
125
126 #[cfg(feature = "alloc")]
132 fn dedup(&self) -> &Dedup<Self>
133 where
134 Self: Sized,
135 {
136 Dedup::new(self)
137 }
138
139 fn is_unique(&self) -> bool {
145 false
146 }
147
148 fn size(&self) -> Option<usize> {
156 None
157 }
158}
159
160impl<'a, P: Props + ?Sized> Props for &'a P {
161 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
162 &'kv self,
163 for_each: F,
164 ) -> ControlFlow<()> {
165 (**self).for_each(for_each)
166 }
167
168 fn get<'v, K: ToStr>(&'v self, key: K) -> Option<Value<'v>> {
169 (**self).get(key)
170 }
171
172 fn pull<'kv, V: FromValue<'kv>, K: ToStr>(&'kv self, key: K) -> Option<V> {
173 (**self).pull(key)
174 }
175
176 fn is_unique(&self) -> bool {
177 (**self).is_unique()
178 }
179
180 fn size(&self) -> Option<usize> {
181 (**self).size()
182 }
183}
184
185impl<P: Props> Props for Option<P> {
186 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
187 &'kv self,
188 for_each: F,
189 ) -> ControlFlow<()> {
190 match self {
191 Some(props) => props.for_each(for_each),
192 None => ControlFlow::Continue(()),
193 }
194 }
195
196 fn get<'v, K: ToStr>(&'v self, key: K) -> Option<Value<'v>> {
197 match self {
198 Some(props) => props.get(key),
199 None => None,
200 }
201 }
202
203 fn pull<'kv, V: FromValue<'kv>, K: ToStr>(&'kv self, key: K) -> Option<V> {
204 match self {
205 Some(props) => props.pull(key),
206 None => None,
207 }
208 }
209
210 fn is_unique(&self) -> bool {
211 match self {
212 Some(props) => props.is_unique(),
213 None => true,
214 }
215 }
216
217 fn size(&self) -> Option<usize> {
218 match self {
219 Some(props) => props.size(),
220 None => Some(0),
221 }
222 }
223}
224
225#[cfg(feature = "alloc")]
226impl<'a, P: Props + ?Sized + 'a> Props for alloc::boxed::Box<P> {
227 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
228 &'kv self,
229 for_each: F,
230 ) -> ControlFlow<()> {
231 (**self).for_each(for_each)
232 }
233
234 fn get<'v, K: ToStr>(&'v self, key: K) -> Option<Value<'v>> {
235 (**self).get(key)
236 }
237
238 fn pull<'kv, V: FromValue<'kv>, K: ToStr>(&'kv self, key: K) -> Option<V> {
239 (**self).pull(key)
240 }
241
242 fn is_unique(&self) -> bool {
243 (**self).is_unique()
244 }
245
246 fn size(&self) -> Option<usize> {
247 (**self).size()
248 }
249}
250
251#[cfg(feature = "alloc")]
252impl<'a, P: Props + ?Sized + 'a> Props for alloc::sync::Arc<P> {
253 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
254 &'kv self,
255 for_each: F,
256 ) -> ControlFlow<()> {
257 (**self).for_each(for_each)
258 }
259
260 fn get<'v, K: ToStr>(&'v self, key: K) -> Option<Value<'v>> {
261 (**self).get(key)
262 }
263
264 fn pull<'kv, V: FromValue<'kv>, K: ToStr>(&'kv self, key: K) -> Option<V> {
265 (**self).pull(key)
266 }
267
268 fn is_unique(&self) -> bool {
269 (**self).is_unique()
270 }
271
272 fn size(&self) -> Option<usize> {
273 (**self).size()
274 }
275}
276
277impl<K: ToStr, V: ToValue> Props for (K, V) {
278 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
279 &'kv self,
280 mut for_each: F,
281 ) -> ControlFlow<()> {
282 for_each(self.0.to_str(), self.1.to_value())
283 }
284
285 fn get<'v, G: ToStr>(&'v self, key: G) -> Option<Value<'v>> {
286 if key.to_str() == self.0.to_str() {
287 Some(self.1.to_value())
288 } else {
289 None
290 }
291 }
292
293 fn is_unique(&self) -> bool {
294 true
295 }
296
297 fn size(&self) -> Option<usize> {
298 Some(1)
299 }
300}
301
302impl<P: Props> Props for [P] {
303 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
304 &'kv self,
305 mut for_each: F,
306 ) -> ControlFlow<()> {
307 for p in self {
308 p.for_each(&mut for_each)?;
309 }
310
311 ControlFlow::Continue(())
312 }
313
314 fn get<'v, G: ToStr>(&'v self, key: G) -> Option<Value<'v>> {
315 let key = key.to_str();
316
317 for p in self {
318 if let Some(value) = p.get(key.by_ref()) {
319 return Some(value);
320 }
321 }
322
323 None
324 }
325
326 fn size(&self) -> Option<usize> {
327 let mut size = 0;
328
329 for p in self {
330 size += p.size()?;
331 }
332
333 Some(size)
334 }
335}
336
337impl<T, const N: usize> Props for [T; N]
338where
339 [T]: Props,
340{
341 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
342 &'kv self,
343 for_each: F,
344 ) -> ControlFlow<()> {
345 Props::for_each(self as &[_], for_each)
346 }
347
348 fn get<'v, K: ToStr>(&'v self, key: K) -> Option<Value<'v>> {
349 Props::get(self as &[_], key)
350 }
351
352 fn pull<'kv, V: FromValue<'kv>, K: ToStr>(&'kv self, key: K) -> Option<V> {
353 Props::pull(self as &[_], key)
354 }
355
356 fn is_unique(&self) -> bool {
357 Props::is_unique(self as &[_])
358 }
359
360 fn size(&self) -> Option<usize> {
361 Props::size(self as &[_])
362 }
363}
364
365impl Props for Empty {
366 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
367 &'kv self,
368 _: F,
369 ) -> ControlFlow<()> {
370 ControlFlow::Continue(())
371 }
372
373 fn get<'v, K: ToStr>(&'v self, _: K) -> Option<Value<'v>> {
374 None
375 }
376
377 fn is_unique(&self) -> bool {
378 true
379 }
380
381 fn size(&self) -> Option<usize> {
382 Some(0)
383 }
384}
385
386impl<A: Props, B: Props> Props for And<A, B> {
387 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
388 &'kv self,
389 mut for_each: F,
390 ) -> ControlFlow<()> {
391 self.left().for_each(&mut for_each)?;
392 self.right().for_each(for_each)
393 }
394
395 fn get<'v, K: ToStr>(&'v self, key: K) -> Option<Value<'v>> {
396 let key = key.borrow();
397
398 self.left().get(key).or_else(|| self.right().get(key))
399 }
400
401 fn size(&self) -> Option<usize> {
402 Some(self.left().size()? + self.right().size()?)
403 }
404}
405
406pub struct Filter<P, F> {
410 props: P,
411 filter: F,
412}
413
414impl<P, F> Filter<P, F> {
415 fn new(props: P, filter: F) -> Self {
416 Filter { props, filter }
417 }
418}
419
420impl<P: Props, F: Fn(Str, Value) -> bool> Props for Filter<P, F> {
421 fn for_each<'kv, T: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
422 &'kv self,
423 mut for_each: T,
424 ) -> ControlFlow<()> {
425 self.props.for_each(|key, value| {
426 if !(self.filter)(key.by_ref(), value.by_ref()) {
427 return ControlFlow::Continue(());
428 }
429
430 for_each(key, value)
431 })
432 }
433
434 fn get<'v, K: ToStr>(&'v self, key: K) -> Option<Value<'v>> {
435 let key = key.to_str();
436
437 self.props
438 .get(key.by_ref())
439 .filter(|v| (self.filter)(key, v.by_ref()))
440 }
441
442 fn is_unique(&self) -> bool {
443 self.props.is_unique()
444 }
445
446 fn size(&self) -> Option<usize> {
447 None
448 }
449}
450
451pub trait FromProps<'kv> {
455 fn from_props<P: Props + ?Sized>(props: &'kv P) -> Self;
462}
463
464#[cfg(feature = "alloc")]
465impl<'kv, 'a, C: FromProps<'kv> + 'a> FromProps<'kv> for alloc::boxed::Box<C> {
466 fn from_props<P: Props + ?Sized>(props: &'kv P) -> Self {
467 alloc::boxed::Box::new(C::from_props(props))
468 }
469}
470
471#[cfg(feature = "alloc")]
472impl<'kv, 'a, C: FromProps<'kv> + 'a> FromProps<'kv> for alloc::sync::Arc<C> {
473 fn from_props<P: Props + ?Sized>(props: &'kv P) -> Self {
474 alloc::sync::Arc::new(C::from_props(props))
475 }
476}
477
478#[cfg(feature = "alloc")]
479mod alloc_support {
480 use super::*;
481
482 use crate::value::OwnedValue;
483
484 use core::{cmp, iter, mem, ptr};
485
486 use alloc::{boxed::Box, collections::BTreeMap, sync::Arc, vec::Vec};
487
488 pub struct OwnedProps {
499 buckets: *const [OwnedPropsBucket],
500 nprops: usize,
501 owner: OwnedPropsOwner,
502 head: Option<*const OwnedProp>,
503 }
504
505 unsafe impl Send for OwnedProps {}
507 unsafe impl Sync for OwnedProps {}
509
510 impl Clone for OwnedProps {
511 fn clone(&self) -> Self {
512 match self.owner {
513 OwnedPropsOwner::Box(_) => {
514 let (nprops, props, head) = OwnedProps::cloned(self);
515
516 OwnedProps::new_owned(nprops, props, head)
517 }
518 OwnedPropsOwner::Shared(ref props) => {
519 OwnedProps::new_shared(self.nprops, props.clone(), self.head)
520 }
521 }
522 }
523 }
524
525 impl Drop for OwnedProps {
526 fn drop(&mut self) {
527 match self.owner {
528 OwnedPropsOwner::Box(boxed) => {
529 drop(unsafe { Box::from_raw(boxed) });
531 }
532 OwnedPropsOwner::Shared(_) => {
533 }
535 }
536 }
537 }
538
539 struct OwnedPropsBucket {
540 head: *mut OwnedProp,
541 tail: Vec<*mut OwnedProp>,
542 }
543
544 impl Drop for OwnedPropsBucket {
545 fn drop(&mut self) {
546 let mut guard = SliceDropGuard::new(&mut self.tail);
547
548 if !self.head.is_null() {
549 drop(unsafe { Box::from_raw(self.head) })
551 }
552
553 unsafe {
555 guard.drop();
556 }
557 }
558 }
559
560 struct OwnedProp {
561 key: Str<'static>,
562 value: OwnedValue,
563 next: Option<*const OwnedProp>,
564 }
565
566 enum OwnedPropsOwner {
567 Box(*mut [OwnedPropsBucket]),
568 Shared(Arc<[OwnedPropsBucket]>),
569 }
570
571 impl OwnedProps {
572 fn cloned(src: &Self) -> (usize, Box<[OwnedPropsBucket]>, Option<*const OwnedProp>) {
573 let nbuckets = src.buckets.len();
578 let mut nprops = 0;
579 let mut buckets = iter::from_fn(|| Some(OwnedPropsBucket::new()))
580 .take(nbuckets)
581 .collect::<Vec<_>>()
582 .into_boxed_slice();
583 let mut head = None::<*const OwnedProp>;
584 let mut tail = None::<*mut OwnedProp>;
585
586 let _ = src.for_each(|prop| {
590 let bucket = &mut buckets[idx(nbuckets, &prop.key)];
591
592 let prop = unsafe {
594 OwnedProp::new(&mut head, &mut tail, prop.key.clone(), prop.value.clone())
595 };
596
597 bucket.push(prop);
598 nprops += 1;
599
600 ControlFlow::Continue(())
601 });
602
603 (nprops, buckets, head)
604 }
605
606 fn new_owned(
607 nprops: usize,
608 buckets: Box<[OwnedPropsBucket]>,
609 head: Option<*const OwnedProp>,
610 ) -> Self {
611 let buckets = Box::into_raw(buckets);
612 let owner = OwnedPropsOwner::Box(buckets);
613
614 OwnedProps {
615 nprops,
616 buckets,
617 owner,
618 head,
619 }
620 }
621
622 fn new_shared(
623 nprops: usize,
624 buckets: Arc<[OwnedPropsBucket]>,
625 head: Option<*const OwnedProp>,
626 ) -> Self {
627 let ptr = Arc::as_ptr(&buckets);
628 let owner = OwnedPropsOwner::Shared(buckets);
629 let buckets = ptr;
630
631 OwnedProps {
632 nprops,
633 buckets,
634 owner,
635 head,
636 }
637 }
638
639 fn collect(
640 props: impl Props,
641 mut key: impl FnMut(Str) -> Str<'static>,
642 mut value: impl FnMut(Value) -> OwnedValue,
643 ) -> (usize, Box<[OwnedPropsBucket]>, Option<*const OwnedProp>) {
644 let nbuckets = cmp::min(128, props.size().unwrap_or(32));
647 let mut nprops = 0;
648 let mut buckets = iter::from_fn(|| Some(OwnedPropsBucket::new()))
649 .take(nbuckets)
650 .collect::<Vec<_>>()
651 .into_boxed_slice();
652 let mut head = None::<*const OwnedProp>;
653 let mut tail = None::<*mut OwnedProp>;
654
655 let _ = props.for_each(|k, v| {
656 let bucket = &mut buckets[idx(nbuckets, &k)];
657
658 if bucket.get(&k).is_some() {
659 ControlFlow::Continue(())
660 } else {
661 let prop = unsafe { OwnedProp::new(&mut head, &mut tail, key(k), value(v)) };
663
664 bucket.push(prop);
665 nprops += 1;
666
667 ControlFlow::Continue(())
668 }
669 });
670
671 (nprops, buckets, head)
672 }
673
674 pub fn collect_owned(props: impl Props) -> Self {
680 let (nprops, buckets, head) = Self::collect(props, |k| k.to_owned(), |v| v.to_owned());
681
682 let buckets = Box::into_raw(buckets);
683 let owner = OwnedPropsOwner::Box(buckets);
684
685 OwnedProps {
686 nprops,
687 buckets,
688 owner,
689 head,
690 }
691 }
692
693 pub fn collect_shared(props: impl Props) -> Self {
699 let (nprops, buckets, head) =
700 Self::collect(props, |k| k.to_shared(), |v| v.to_shared());
701
702 Self::new_shared(nprops, buckets.into(), head)
703 }
704
705 pub fn to_shared(&self) -> Self {
711 match self.owner {
712 OwnedPropsOwner::Box(_) => {
713 let (nprops, buckets, head) = OwnedProps::cloned(self);
715
716 Self::new_shared(nprops, Arc::from(buckets), head)
717 }
718 OwnedPropsOwner::Shared(ref owner) => {
719 OwnedProps::new_shared(self.nprops, owner.clone(), self.head)
720 }
721 }
722 }
723
724 fn for_each<'kv, F: FnMut(&'kv OwnedProp) -> ControlFlow<()>>(
725 &'kv self,
726 mut for_each: F,
727 ) -> ControlFlow<()> {
728 let mut next = self.head;
730
731 while let Some(current) = next.take() {
732 let current = unsafe { &*current };
735
736 for_each(¤t)?;
737
738 next = current.next;
739 }
740
741 ControlFlow::Continue(())
742 }
743
744 fn get<'v, K: ToStr>(&'v self, key: K) -> Option<&'v OwnedProp> {
745 let key = key.to_str();
746
747 let buckets = unsafe { &*self.buckets };
749
750 buckets[idx(buckets.len(), &key)].get(&key)
751 }
752 }
753
754 impl Props for OwnedProps {
755 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
756 &'kv self,
757 mut for_each: F,
758 ) -> ControlFlow<()> {
759 self.for_each(|prop| for_each(prop.key.by_ref(), prop.value.by_ref()))
760 }
761
762 fn get<'v, K: ToStr>(&'v self, key: K) -> Option<Value<'v>> {
763 self.get(key).map(|prop| prop.value.by_ref())
764 }
765
766 fn is_unique(&self) -> bool {
767 true
768 }
769
770 fn size(&self) -> Option<usize> {
771 Some(self.nprops)
772 }
773 }
774
775 impl<'kv> FromProps<'kv> for OwnedProps {
776 fn from_props<P: Props + ?Sized>(props: &'kv P) -> Self {
777 Self::collect_owned(props)
778 }
779 }
780
781 impl OwnedPropsBucket {
782 fn new() -> OwnedPropsBucket {
783 OwnedPropsBucket {
784 head: ptr::null_mut(),
785 tail: Vec::new(),
786 }
787 }
788
789 fn push(&mut self, mut prop: PropDropGuard) {
790 if self.head.is_null() {
791 self.head = prop.take();
792 } else {
793 self.tail.reserve(1);
794 self.tail.push(prop.take());
795 }
796 }
797
798 fn get(&self, k: &Str) -> Option<&OwnedProp> {
799 if !self.head.is_null() {
800 let prop = unsafe { &*self.head };
802
803 if prop.key == *k {
804 return Some(&prop);
805 }
806 }
807
808 for prop in &self.tail {
809 let prop = unsafe { &**prop };
811
812 if prop.key == *k {
813 return Some(&prop);
814 }
815 }
816
817 None
818 }
819 }
820
821 impl OwnedProp {
822 unsafe fn new(
824 head: &mut Option<*const OwnedProp>,
825 tail: &mut Option<*mut OwnedProp>,
826 key: Str<'static>,
827 value: OwnedValue,
828 ) -> PropDropGuard {
829 let guard = PropDropGuard::new(Box::new(OwnedProp {
830 key,
831 value,
832 next: None,
833 }));
834
835 let prop_ptr = guard.0;
836
837 *head = head.or_else(|| Some(prop_ptr));
838
839 if let Some(tail) = tail {
840 debug_assert!(head.is_some());
841
842 let tail = unsafe { &mut **tail };
844
845 debug_assert!(tail.next.is_none());
846 tail.next = Some(prop_ptr);
847 }
848 *tail = Some(prop_ptr);
849
850 guard
851 }
852 }
853
854 struct SliceDropGuard<'a> {
855 idx: usize,
856 value: &'a mut [*mut OwnedProp],
857 }
858
859 impl<'a> Drop for SliceDropGuard<'a> {
860 fn drop(&mut self) {
861 unsafe {
864 self.drop();
865 }
866 }
867 }
868
869 impl<'a> SliceDropGuard<'a> {
870 fn new(value: &'a mut [*mut OwnedProp]) -> Self {
871 SliceDropGuard { value, idx: 0 }
872 }
873
874 unsafe fn drop(&mut self) {
876 while self.idx < self.value.len() {
877 let prop = self.value[self.idx];
878 self.idx += 1;
879
880 drop(unsafe { Box::from_raw(prop) });
882 }
883 }
884 }
885
886 struct PropDropGuard(*mut OwnedProp);
887
888 impl PropDropGuard {
889 fn new(prop: Box<OwnedProp>) -> Self {
890 PropDropGuard(Box::into_raw(prop))
891 }
892
893 fn take(&mut self) -> *mut OwnedProp {
894 mem::replace(&mut self.0, ptr::null_mut())
895 }
896 }
897
898 impl Drop for PropDropGuard {
899 fn drop(&mut self) {
900 if self.0.is_null() {
901 return;
902 }
903
904 drop(unsafe { Box::from_raw(self.0) });
906 }
907 }
908
909 fn idx(buckets: usize, k: &Str) -> usize {
910 let mut hash = 0xcbf29ce484222325;
911
912 for b in k.get().as_bytes() {
913 hash = hash ^ (*b as u64);
914 hash = hash.wrapping_mul(0x00000100000001b3);
915 }
916
917 (hash as usize) % buckets
918 }
919
920 #[repr(transparent)]
928 pub struct Dedup<P: ?Sized>(P);
929
930 impl<P: ?Sized> Dedup<P> {
931 pub(super) fn new<'a>(props: &'a P) -> &'a Dedup<P> {
932 unsafe { &*(props as *const P as *const Dedup<P>) }
934 }
935 }
936
937 impl<P: Props + ?Sized> Props for Dedup<P> {
938 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
939 &'kv self,
940 mut for_each: F,
941 ) -> ControlFlow<()> {
942 enum Filter<'a> {
948 Inline(Inline<'a, 16>),
949 Spilled(Spilled<'a>),
950 }
951
952 impl<'a> Filter<'a> {
953 fn new(size: Option<usize>) -> Self {
954 match size {
955 Some(size) if size <= 16 => Filter::Inline(Inline::new()),
956 _ => Filter::Spilled(Spilled::new()),
957 }
958 }
959
960 fn insert(&mut self, key: Str<'a>, value: Value<'a>) {
961 match self {
962 Filter::Inline(ref mut inline) => match inline.insert(key, value) {
963 Ok(()) => (),
964 Err((key, value)) => {
965 let mut spilled = Spilled::spill(inline.take());
966 spilled.insert(key, value);
967
968 *self = Filter::Spilled(spilled);
969 }
970 },
971 Filter::Spilled(ref mut spilled) => spilled.insert(key, value),
972 }
973 }
974
975 fn take<'b>(&'b mut self) -> impl Iterator<Item = (Str<'a>, Value<'a>)> + 'b {
976 enum Either<A, B> {
977 A(A),
978 B(B),
979 }
980
981 impl<T, A: Iterator<Item = T>, B: Iterator<Item = T>> Iterator for Either<A, B> {
982 type Item = T;
983
984 fn next(&mut self) -> Option<Self::Item> {
985 match self {
986 Either::A(a) => a.next(),
987 Either::B(b) => b.next(),
988 }
989 }
990 }
991
992 match self {
993 Filter::Inline(ref mut inline) => Either::A(inline.take()),
994 Filter::Spilled(ref mut spilled) => Either::B(spilled.take()),
995 }
996 }
997 }
998
999 struct Inline<'a, const N: usize> {
1000 values: [(Str<'a>, Value<'a>); N],
1001 len: usize,
1002 }
1003
1004 impl<'a, const N: usize> Inline<'a, N> {
1005 fn new() -> Self {
1006 Inline {
1007 values: [const { (Str::new(""), Value::null()) }; N],
1008 len: 0,
1009 }
1010 }
1011
1012 fn insert(
1013 &mut self,
1014 key: Str<'a>,
1015 value: Value<'a>,
1016 ) -> Result<(), (Str<'a>, Value<'a>)> {
1017 if self.len == N {
1018 return Err((key, value));
1019 }
1020
1021 for (seen, _) in &self.values[..self.len] {
1022 if *seen == key {
1023 return Ok(());
1024 }
1025 }
1026
1027 self.values[self.len] = (key, value);
1028 self.len += 1;
1029
1030 Ok(())
1031 }
1032
1033 fn take<'b>(&'b mut self) -> impl Iterator<Item = (Str<'a>, Value<'a>)> + 'b {
1034 let len = self.len;
1035 self.len = 0;
1036
1037 (&mut self.values[..len])
1038 .into_iter()
1039 .map(|v| mem::replace(v, (Str::new(""), Value::null())))
1040 }
1041 }
1042
1043 struct Spilled<'a> {
1044 values: BTreeMap<Str<'a>, Value<'a>>,
1045 }
1046
1047 impl<'a> Spilled<'a> {
1048 fn new() -> Self {
1049 Spilled {
1050 values: Default::default(),
1051 }
1052 }
1053
1054 fn spill(seen: impl Iterator<Item = (Str<'a>, Value<'a>)>) -> Self {
1055 Spilled {
1056 values: seen.collect(),
1057 }
1058 }
1059
1060 fn insert(&mut self, key: Str<'a>, value: Value<'a>) {
1061 self.values.entry(key).or_insert(value);
1062 }
1063
1064 fn take<'b>(&'b mut self) -> impl Iterator<Item = (Str<'a>, Value<'a>)> + 'b {
1065 mem::take(&mut self.values).into_iter()
1066 }
1067 }
1068
1069 if self.0.is_unique() {
1071 return self.0.for_each(for_each);
1072 }
1073
1074 let mut filter = Filter::new(self.0.size());
1075
1076 let _ = self.0.for_each(|key, value| {
1080 filter.insert(key, value);
1081
1082 ControlFlow::Continue(())
1083 });
1084
1085 for (key, value) in filter.take() {
1086 for_each(key, value)?;
1087 }
1088
1089 ControlFlow::Continue(())
1090 }
1091
1092 fn get<'v, K: ToStr>(&'v self, key: K) -> Option<Value<'v>> {
1093 self.0.get(key)
1094 }
1095
1096 fn is_unique(&self) -> bool {
1097 true
1098 }
1099
1100 fn size(&self) -> Option<usize> {
1101 self.0.size()
1104 }
1105 }
1106
1107 impl<T: Props> Props for Vec<T> {
1108 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
1109 &'kv self,
1110 for_each: F,
1111 ) -> ControlFlow<()> {
1112 Props::for_each(self as &[_], for_each)
1113 }
1114
1115 fn get<'v, K: ToStr>(&'v self, key: K) -> Option<Value<'v>> {
1116 Props::get(self as &[_], key)
1117 }
1118
1119 fn pull<'kv, V: FromValue<'kv>, K: ToStr>(&'kv self, key: K) -> Option<V> {
1120 Props::pull(self as &[_], key)
1121 }
1122
1123 fn is_unique(&self) -> bool {
1124 Props::is_unique(self as &[_])
1125 }
1126
1127 fn size(&self) -> Option<usize> {
1128 Props::size(self as &[_])
1129 }
1130 }
1131
1132 impl<'kv, K, V> FromProps<'kv> for Vec<(K, V)>
1133 where
1134 K: From<Str<'kv>>,
1135 V: From<Value<'kv>>,
1136 {
1137 fn from_props<P: Props + ?Sized>(props: &'kv P) -> Self {
1138 let mut result = Vec::new();
1139
1140 let _ = props.for_each(|k, v| {
1141 result.push((k.into(), v.into()));
1142
1143 ControlFlow::Continue(())
1144 });
1145
1146 result
1147 }
1148 }
1149
1150 impl<K, V> Props for BTreeMap<K, V>
1151 where
1152 K: Ord + ToStr + Borrow<str>,
1153 V: ToValue,
1154 {
1155 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
1156 &'kv self,
1157 mut for_each: F,
1158 ) -> ControlFlow<()> {
1159 for (k, v) in self {
1160 for_each(k.to_str(), v.to_value())?;
1161 }
1162
1163 ControlFlow::Continue(())
1164 }
1165
1166 fn get<'v, Q: ToStr>(&'v self, key: Q) -> Option<Value<'v>> {
1167 self.get(key.to_str().as_ref()).map(|v| v.to_value())
1168 }
1169
1170 fn is_unique(&self) -> bool {
1171 true
1172 }
1173
1174 fn size(&self) -> Option<usize> {
1175 Some(self.len())
1176 }
1177 }
1178
1179 impl<'kv, K, V> FromProps<'kv> for BTreeMap<K, V>
1180 where
1181 K: Ord + From<Str<'kv>>,
1182 V: From<Value<'kv>>,
1183 {
1184 fn from_props<P: Props + ?Sized>(props: &'kv P) -> Self {
1185 let mut result = BTreeMap::new();
1186
1187 let _ = props.for_each(|k, v| {
1188 result.entry(k.into()).or_insert_with(|| v.into());
1189
1190 ControlFlow::Continue(())
1191 });
1192
1193 result
1194 }
1195 }
1196
1197 #[cfg(test)]
1198 mod tests {
1199 use super::*;
1200
1201 use crate::value::OwnedValue;
1202
1203 #[test]
1204 fn btreemap_props() {
1205 let props = BTreeMap::from_iter([("a", 1), ("b", 2), ("c", 3)]);
1206
1207 assert_eq!(1, Props::get(&props, "a").unwrap().cast::<i32>().unwrap());
1208 assert_eq!(2, Props::get(&props, "b").unwrap().cast::<i32>().unwrap());
1209 assert_eq!(3, Props::get(&props, "c").unwrap().cast::<i32>().unwrap());
1210
1211 assert_eq!(1, Props::pull::<i32, _>(&props, "a").unwrap());
1212 assert_eq!(2, Props::pull::<i32, _>(&props, "b").unwrap());
1213 assert_eq!(3, Props::pull::<i32, _>(&props, "c").unwrap());
1214
1215 assert!(props.is_unique());
1216 }
1217
1218 #[test]
1219 fn btreemap_from_props() {
1220 let props = BTreeMap::<String, OwnedValue>::from_props(&[("a", 1), ("a", 2), ("c", 3)]);
1221
1222 assert_eq!(1, Props::pull::<i32, _>(&props, "a").unwrap());
1223 assert_eq!(3, Props::pull::<i32, _>(&props, "c").unwrap());
1224 }
1225
1226 #[test]
1227 fn vec_from_props() {
1228 let props = Vec::<(String, OwnedValue)>::from_props(&[("a", 1), ("a", 2), ("c", 3)]);
1229
1230 assert_eq!(3, props.len());
1231
1232 assert_eq!(1, Props::pull::<i32, _>(&props, "a").unwrap());
1233 assert_eq!(3, Props::pull::<i32, _>(&props, "c").unwrap());
1234 }
1235
1236 #[test]
1237 fn dedup() {
1238 let props = [
1239 ("a", Value::from(1)),
1240 ("a", Value::from(2)),
1241 ("b", Value::from(1)),
1242 ];
1243
1244 let deduped = props.dedup();
1245
1246 let mut ac = 0;
1247 let mut bc = 0;
1248
1249 let _ = deduped.for_each(|k, v| {
1250 match k.get() {
1251 "a" => {
1252 assert_eq!(1, v.cast::<i32>().unwrap());
1253 ac += 1;
1254 }
1255 "b" => {
1256 assert_eq!(1, v.cast::<i32>().unwrap());
1257 bc += 1;
1258 }
1259 _ => (),
1260 }
1261
1262 ControlFlow::Continue(())
1263 });
1264
1265 assert_eq!(1, ac);
1266 assert_eq!(1, bc);
1267 }
1268
1269 #[test]
1270 fn dedup_many() {
1271 let props = [
1272 ("aumcgyiuerskg", 1),
1273 ("blvkmnfdigmgc", 2),
1274 ("cvojdfmcisemc", 3),
1275 ("dlkgjhmgkvnrd", 4),
1276 ("eiugrlgmvmgvd", 5),
1277 ("flfbjhmrimrtw", 6),
1278 ("goihudvngusrg", 7),
1279 ("hfjehrngviuwn", 8),
1280 ("ivojitvnjysns", 9),
1281 ("jciughnrhiens", 10),
1282 ("kofhfuernytnd", 11),
1283 ("lvgjrunfwwner", 12),
1284 ("mfjerukfnjhns", 13),
1285 ("nmorikjnnehsx", 14),
1286 ("oiovjrmunsnex", 15),
1287 ("pijdshfenrnfq", 16),
1288 ("aumcgyiuerskg", 11),
1289 ("blvkmnfdigmgc", 21),
1290 ("cvojdfmcisemc", 31),
1291 ("dlkgjhmgkvnrd", 41),
1292 ("eiugrlgmvmgvd", 51),
1293 ("flfbjhmrimrtw", 61),
1294 ("goihudvngusrg", 71),
1295 ("hfjehrngviuwn", 81),
1296 ("ivojitvnjysns", 91),
1297 ("jciughnrhiens", 101),
1298 ("kofhfuernytnd", 111),
1299 ("lvgjrunfwwner", 121),
1300 ("mfjerukfnjhns", 131),
1301 ("nmorikjnnehsx", 141),
1302 ("oiovjrmunsnex", 151),
1303 ("pijdshfenrnfq", 161),
1304 ];
1305
1306 let deduped = props.dedup();
1307
1308 let mut ac = 0;
1309 let mut bc = 0;
1310
1311 let _ = deduped.for_each(|k, v| {
1312 match k.get() {
1313 "aumcgyiuerskg" => {
1314 assert_eq!(1, v.cast::<i32>().unwrap());
1315 ac += 1;
1316 }
1317 "blvkmnfdigmgc" => {
1318 assert_eq!(2, v.cast::<i32>().unwrap());
1319 bc += 1;
1320 }
1321 _ => (),
1322 }
1323
1324 ControlFlow::Continue(())
1325 });
1326
1327 assert_eq!(1, ac);
1328 assert_eq!(1, bc);
1329 }
1330
1331 struct WrongSize<P> {
1332 props: P,
1333 size: Option<usize>,
1334 }
1335
1336 impl<P: Props> Props for WrongSize<P> {
1337 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
1338 &'kv self,
1339 for_each: F,
1340 ) -> ControlFlow<()> {
1341 self.props.for_each(for_each)
1342 }
1343
1344 fn size(&self) -> Option<usize> {
1345 self.size
1346 }
1347 }
1348
1349 #[test]
1350 fn dedup_low_ball_size() {
1351 let props = WrongSize {
1352 props: [
1353 ("aumcgyiuerskg", 1),
1354 ("blvkmnfdigmgc", 2),
1355 ("cvojdfmcisemc", 3),
1356 ("dlkgjhmgkvnrd", 4),
1357 ("eiugrlgmvmgvd", 5),
1358 ("flfbjhmrimrtw", 6),
1359 ("goihudvngusrg", 7),
1360 ("hfjehrngviuwn", 8),
1361 ("ivojitvnjysns", 9),
1362 ("jciughnrhiens", 10),
1363 ("kofhfuernytnd", 11),
1364 ("lvgjrunfwwner", 12),
1365 ("mfjerukfnjhns", 13),
1366 ("nmorikjnnehsx", 14),
1367 ("oiovjrmunsnex", 15),
1368 ("pijdshfenrnfq", 16),
1369 ("rkjhfngjrfnhf", 17),
1370 ],
1371 size: Some(1),
1372 };
1373
1374 let deduped = props.dedup();
1375
1376 let mut count = 0;
1377
1378 let _ = deduped.for_each(|_, _| {
1379 count += 1;
1380
1381 ControlFlow::Continue(())
1382 });
1383
1384 assert_eq!(17, count);
1385 }
1386
1387 #[test]
1388 fn dedup_high_ball_size() {
1389 let props = WrongSize {
1390 props: [("aumcgyiuerskg", 1)],
1391 size: Some(usize::MAX),
1392 };
1393
1394 let deduped = props.dedup();
1395
1396 let mut count = 0;
1397
1398 let _ = deduped.for_each(|_, _| {
1399 count += 1;
1400
1401 ControlFlow::Continue(())
1402 });
1403
1404 assert_eq!(1, count);
1405 }
1406
1407 #[test]
1408 fn owned_props_empty() {
1409 let props = OwnedProps::collect_owned([] as [(Str, Value); 0]);
1410
1411 assert_eq!(Some(0), props.size());
1412 assert!(props.is_unique());
1413
1414 let mut count = 0;
1415
1416 let _ = props.for_each(|_| {
1417 count += 1;
1418 ControlFlow::Continue(())
1419 });
1420
1421 assert_eq!(0, count);
1422 }
1423
1424 #[test]
1425 fn owned_props_collect() {
1426 for (description, case) in [
1427 (
1428 "owned",
1429 OwnedProps::collect_owned([
1430 ("b", 2),
1431 ("a", 1),
1432 ("c", 3),
1433 ("b", 12),
1434 ("a", 11),
1435 ("c", 13),
1436 ]),
1437 ),
1438 (
1439 "shared",
1440 OwnedProps::collect_shared([
1441 ("b", 2),
1442 ("a", 1),
1443 ("c", 3),
1444 ("b", 12),
1445 ("a", 11),
1446 ("c", 13),
1447 ]),
1448 ),
1449 (
1450 "owned -> shared",
1451 OwnedProps::collect_owned([
1452 ("b", 2),
1453 ("a", 1),
1454 ("c", 3),
1455 ("b", 12),
1456 ("a", 11),
1457 ("c", 13),
1458 ])
1459 .to_shared(),
1460 ),
1461 (
1462 "shared -> shared",
1463 OwnedProps::collect_shared([
1464 ("b", 2),
1465 ("a", 1),
1466 ("c", 3),
1467 ("b", 12),
1468 ("a", 11),
1469 ("c", 13),
1470 ])
1471 .to_shared(),
1472 ),
1473 (
1474 "owned -> clone",
1475 OwnedProps::collect_owned([
1476 ("b", 2),
1477 ("a", 1),
1478 ("c", 3),
1479 ("b", 12),
1480 ("a", 11),
1481 ("c", 13),
1482 ])
1483 .clone(),
1484 ),
1485 (
1486 "shared -> clone",
1487 OwnedProps::collect_shared([
1488 ("b", 2),
1489 ("a", 1),
1490 ("c", 3),
1491 ("b", 12),
1492 ("a", 11),
1493 ("c", 13),
1494 ])
1495 .clone(),
1496 ),
1497 ] {
1498 assert_eq!(Some(3), case.size());
1499 assert!(case.is_unique());
1500
1501 assert_eq!(Some(1), case.pull::<usize, _>("a"), "{description}");
1502 assert_eq!(Some(2), case.pull::<usize, _>("b"), "{description}");
1503 assert_eq!(Some(3), case.pull::<usize, _>("c"), "{description}");
1504
1505 let mut values = Vec::new();
1506
1507 let _ = case.for_each(|prop| {
1508 values.push((prop.key.get(), prop.value.by_ref().cast::<usize>()));
1509 ControlFlow::Continue(())
1510 });
1511
1512 assert_eq!(
1513 vec![("b", Some(2)), ("a", Some(1)), ("c", Some(3))],
1514 values,
1515 "{description}"
1516 );
1517 }
1518 }
1519 }
1520}
1521
1522#[cfg(feature = "alloc")]
1523pub use alloc_support::*;
1524
1525#[cfg(feature = "std")]
1526mod std_support {
1527 use super::*;
1528
1529 use std::{collections::HashMap, hash::Hash};
1530
1531 impl<K, V> Props for HashMap<K, V>
1532 where
1533 K: Eq + Hash + ToStr + Borrow<str>,
1534 V: ToValue,
1535 {
1536 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
1537 &'kv self,
1538 mut for_each: F,
1539 ) -> ControlFlow<()> {
1540 for (k, v) in self {
1541 for_each(k.to_str(), v.to_value())?;
1542 }
1543
1544 ControlFlow::Continue(())
1545 }
1546
1547 fn get<'v, Q: ToStr>(&'v self, key: Q) -> Option<Value<'v>> {
1548 self.get(key.to_str().as_ref()).map(|v| v.to_value())
1549 }
1550
1551 fn is_unique(&self) -> bool {
1552 true
1553 }
1554
1555 fn size(&self) -> Option<usize> {
1556 Some(self.len())
1557 }
1558 }
1559
1560 impl<'kv, K, V> FromProps<'kv> for HashMap<K, V>
1561 where
1562 K: Eq + Hash + From<Str<'kv>>,
1563 V: From<Value<'kv>>,
1564 {
1565 fn from_props<P: Props + ?Sized>(props: &'kv P) -> Self {
1566 let mut result = HashMap::new();
1567
1568 let _ = props.for_each(|k, v| {
1569 result.entry(k.into()).or_insert_with(|| v.into());
1570
1571 ControlFlow::Continue(())
1572 });
1573
1574 result
1575 }
1576 }
1577
1578 #[cfg(test)]
1579 mod tests {
1580 use super::*;
1581
1582 use crate::value::OwnedValue;
1583
1584 #[test]
1585 fn hashmap_props() {
1586 let props = HashMap::from_iter([("a", 1), ("b", 2), ("c", 3)]);
1587
1588 assert_eq!(1, Props::get(&props, "a").unwrap().cast::<i32>().unwrap());
1589 assert_eq!(2, Props::get(&props, "b").unwrap().cast::<i32>().unwrap());
1590 assert_eq!(3, Props::get(&props, "c").unwrap().cast::<i32>().unwrap());
1591
1592 assert_eq!(1, Props::pull::<i32, _>(&props, "a").unwrap());
1593 assert_eq!(2, Props::pull::<i32, _>(&props, "b").unwrap());
1594 assert_eq!(3, Props::pull::<i32, _>(&props, "c").unwrap());
1595
1596 assert!(props.is_unique());
1597 }
1598
1599 #[test]
1600 fn hashmap_from_props() {
1601 let props = HashMap::<String, OwnedValue>::from_props(&[("a", 1), ("a", 2), ("c", 3)]);
1602
1603 assert_eq!(1, Props::pull::<i32, _>(&props, "a").unwrap());
1604 assert_eq!(3, Props::pull::<i32, _>(&props, "c").unwrap());
1605 }
1606 }
1607}
1608
1609#[repr(transparent)]
1615pub struct AsMap<P: ?Sized>(P);
1616
1617impl<P: ?Sized> AsMap<P> {
1618 fn new<'a>(props: &'a P) -> &'a AsMap<P> {
1619 unsafe { &*(props as *const P as *const AsMap<P>) }
1621 }
1622}
1623
1624impl<P: Props + ?Sized> Props for AsMap<P> {
1625 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
1626 &'kv self,
1627 for_each: F,
1628 ) -> ControlFlow<()> {
1629 self.0.for_each(for_each)
1630 }
1631
1632 fn get<'v, K: ToStr>(&'v self, key: K) -> Option<Value<'v>> {
1633 self.0.get(key)
1634 }
1635
1636 fn pull<'kv, V: FromValue<'kv>, K: ToStr>(&'kv self, key: K) -> Option<V> {
1637 self.0.pull(key)
1638 }
1639
1640 fn is_unique(&self) -> bool {
1641 self.0.is_unique()
1642 }
1643
1644 fn size(&self) -> Option<usize> {
1645 self.0.size()
1646 }
1647}
1648
1649#[cfg(feature = "sval")]
1650impl<P: Props + ?Sized> sval::Value for AsMap<P> {
1651 fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> sval::Result {
1652 stream.map_begin(None)?;
1653
1654 let mut r = Ok(());
1655 let _ = self.for_each(|k, v| {
1656 r = (|| {
1657 stream.map_key_begin()?;
1658 sval_ref::stream_ref(&mut *stream, k)?;
1659 stream.map_key_end()?;
1660
1661 stream.map_value_begin()?;
1662 sval_ref::stream_ref(&mut *stream, v)?;
1663 stream.map_value_end()
1664 })();
1665
1666 if r.is_ok() {
1667 ControlFlow::Continue(())
1668 } else {
1669 ControlFlow::Break(())
1670 }
1671 });
1672 r?;
1673
1674 stream.map_end()
1675 }
1676}
1677
1678#[cfg(feature = "serde")]
1679impl<P: Props + ?Sized> serde::Serialize for AsMap<P> {
1680 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1681 use serde::ser::SerializeMap as _;
1682
1683 let mut err = None;
1684
1685 let mut map = serializer.serialize_map(None)?;
1686
1687 let _ = self.for_each(|k, v| match map.serialize_entry(&k, &v) {
1688 Ok(()) => ControlFlow::Continue(()),
1689 Err(e) => {
1690 err = Some(e);
1691 ControlFlow::Break(())
1692 }
1693 });
1694
1695 if let Some(e) = err {
1696 return Err(e);
1697 }
1698
1699 map.end()
1700 }
1701}
1702
1703impl<P: Props + ?Sized> fmt::Debug for AsMap<P> {
1704 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1705 fmt::Display::fmt(self, f)
1706 }
1707}
1708
1709impl<P: Props + ?Sized> fmt::Display for AsMap<P> {
1710 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1711 let mut map = f.debug_map();
1712
1713 let _ = self.for_each(|k, v| {
1714 map.entry(&k, &v);
1715
1716 ControlFlow::Continue(())
1717 });
1718
1719 map.finish()
1720 }
1721}
1722
1723mod internal {
1724 use core::ops::ControlFlow;
1725
1726 use crate::{str::Str, value::Value};
1727
1728 pub trait DispatchProps {
1729 fn dispatch_for_each<'kv, 'f>(
1730 &'kv self,
1731 for_each: &'f mut dyn FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>,
1732 ) -> ControlFlow<()>;
1733
1734 fn dispatch_get(&self, key: Str) -> Option<Value<'_>>;
1735
1736 fn dispatch_is_unique(&self) -> bool;
1737
1738 fn dispatch_size(&self) -> Option<usize>;
1739 }
1740
1741 pub trait SealedProps {
1742 fn erase_props(&self) -> crate::internal::Erased<&dyn DispatchProps>;
1743 }
1744}
1745
1746pub trait ErasedProps: internal::SealedProps {}
1752
1753impl<P: Props> ErasedProps for P {}
1754
1755impl<P: Props> internal::SealedProps for P {
1756 fn erase_props(&self) -> crate::internal::Erased<&dyn internal::DispatchProps> {
1757 crate::internal::Erased(self)
1758 }
1759}
1760
1761impl<P: Props> internal::DispatchProps for P {
1762 fn dispatch_for_each<'kv, 'f>(
1763 &'kv self,
1764 for_each: &'f mut dyn FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>,
1765 ) -> ControlFlow<()> {
1766 self.for_each(for_each)
1767 }
1768
1769 fn dispatch_get<'v>(&'v self, key: Str) -> Option<Value<'v>> {
1770 self.get(key)
1771 }
1772
1773 fn dispatch_is_unique(&self) -> bool {
1774 self.is_unique()
1775 }
1776
1777 fn dispatch_size(&self) -> Option<usize> {
1778 self.size()
1779 }
1780}
1781
1782impl<'a> Props for dyn ErasedProps + 'a {
1783 fn for_each<'kv, F: FnMut(Str<'kv>, Value<'kv>) -> ControlFlow<()>>(
1784 &'kv self,
1785 mut for_each: F,
1786 ) -> ControlFlow<()> {
1787 self.erase_props().0.dispatch_for_each(&mut for_each)
1788 }
1789
1790 fn get<'v, K: ToStr>(&'v self, key: K) -> Option<Value<'v>> {
1791 self.erase_props().0.dispatch_get(key.to_str())
1792 }
1793
1794 fn is_unique(&self) -> bool {
1795 self.erase_props().0.dispatch_is_unique()
1796 }
1797
1798 fn size(&self) -> Option<usize> {
1799 self.erase_props().0.dispatch_size()
1800 }
1801}
1802
1803#[cfg(test)]
1804mod tests {
1805 use super::*;
1806
1807 #[test]
1808 fn tuple_props() {
1809 let props = ("a", 1);
1810
1811 assert_eq!(1, props.get("a").unwrap().cast::<i32>().unwrap());
1812
1813 assert_eq!(1, props.pull::<i32, _>("a").unwrap());
1814
1815 assert!(props.is_unique());
1816 }
1817
1818 #[test]
1819 fn array_props() {
1820 let props = [("a", 1), ("b", 2), ("c", 3)];
1821
1822 assert_eq!(1, props.get("a").unwrap().cast::<i32>().unwrap());
1823 assert_eq!(2, props.get("b").unwrap().cast::<i32>().unwrap());
1824 assert_eq!(3, props.get("c").unwrap().cast::<i32>().unwrap());
1825
1826 assert_eq!(1, props.pull::<i32, _>("a").unwrap());
1827 assert_eq!(2, props.pull::<i32, _>("b").unwrap());
1828 assert_eq!(3, props.pull::<i32, _>("c").unwrap());
1829
1830 assert!(!props.is_unique());
1831 }
1832
1833 #[test]
1834 fn option_props() {
1835 for (props, expected) in [(Some(("a", 1)), Some(1)), (None, None)] {
1836 assert_eq!(expected, props.pull::<i32, _>("a"));
1837 }
1838 }
1839
1840 #[test]
1841 fn erased_props() {
1842 let props = ("a", 1);
1843
1844 let props = &props as &dyn ErasedProps;
1845
1846 assert_eq!(1, props.get("a").unwrap().cast::<i32>().unwrap());
1847
1848 assert_eq!(1, props.pull::<i32, _>("a").unwrap());
1849
1850 assert!(props.is_unique());
1851 }
1852
1853 #[test]
1854 fn get() {
1855 let props = [("a", 1), ("a", 2)];
1856
1857 assert_eq!(1, props.get("a").unwrap().cast::<i32>().unwrap());
1858 }
1859
1860 #[test]
1861 fn pull() {
1862 let props = [("a", 1), ("a", 2)];
1863
1864 assert_eq!(1, props.pull::<i32, _>("a").unwrap());
1865 }
1866
1867 #[test]
1868 fn size() {
1869 let props = [("a", 1), ("b", 2)].and_props([("c", 3)]);
1870
1871 assert_eq!(Some(3), props.size());
1872 }
1873
1874 #[test]
1875 fn and_props() {
1876 let a = ("a", 1);
1877 let b = [("b", 2), ("c", 3)];
1878
1879 let props = a.and_props(b);
1880
1881 assert_eq!(1, props.get("a").unwrap().cast::<i32>().unwrap());
1882 assert_eq!(2, props.get("b").unwrap().cast::<i32>().unwrap());
1883 assert_eq!(3, props.get("c").unwrap().cast::<i32>().unwrap());
1884
1885 assert_eq!(1, props.pull::<i32, _>("a").unwrap());
1886 assert_eq!(2, props.pull::<i32, _>("b").unwrap());
1887 assert_eq!(3, props.pull::<i32, _>("c").unwrap());
1888
1889 assert!(!props.is_unique());
1890 }
1891
1892 #[test]
1893 fn as_map() {
1894 let props = [("a", 1), ("b", 2)].as_map();
1895
1896 assert_eq!("{\"a\": 1, \"b\": 2}", props.to_string());
1897 }
1898
1899 #[cfg(feature = "sval")]
1900 #[test]
1901 fn as_map_stream() {
1902 let props = [("a", 1), ("b", 2)].as_map();
1903
1904 sval_test::assert_tokens(
1905 &props,
1906 &[
1907 sval_test::Token::MapBegin(None),
1908 sval_test::Token::MapKeyBegin,
1909 sval_test::Token::TextBegin(Some(1)),
1910 sval_test::Token::TextFragmentComputed("a".to_owned()),
1911 sval_test::Token::TextEnd,
1912 sval_test::Token::MapKeyEnd,
1913 sval_test::Token::MapValueBegin,
1914 sval_test::Token::I64(1),
1915 sval_test::Token::MapValueEnd,
1916 sval_test::Token::MapKeyBegin,
1917 sval_test::Token::TextBegin(Some(1)),
1918 sval_test::Token::TextFragmentComputed("b".to_owned()),
1919 sval_test::Token::TextEnd,
1920 sval_test::Token::MapKeyEnd,
1921 sval_test::Token::MapValueBegin,
1922 sval_test::Token::I64(2),
1923 sval_test::Token::MapValueEnd,
1924 sval_test::Token::MapEnd,
1925 ],
1926 );
1927 }
1928
1929 #[cfg(feature = "serde")]
1930 #[test]
1931 fn as_map_serialize() {
1932 let props = [("a", 1), ("b", 2)].as_map();
1933
1934 serde_test::assert_ser_tokens(
1935 &props,
1936 &[
1937 serde_test::Token::Map { len: None },
1938 serde_test::Token::Str("a"),
1939 serde_test::Token::I64(1),
1940 serde_test::Token::Str("b"),
1941 serde_test::Token::I64(2),
1942 serde_test::Token::MapEnd,
1943 ],
1944 );
1945 }
1946
1947 #[test]
1948 fn filter() {
1949 let props =
1950 [("a", 1), ("b", 2), ("c", 3)].filter(|k, v| k == "a" || v.cast::<usize>() == Some(3));
1951
1952 assert!(props.get("a").is_some());
1953 assert!(props.get("b").is_none());
1954 assert!(props.get("c").is_some());
1955 }
1956}