1use crate::callsite;
39use core::{
40 borrow::Borrow,
41 fmt::{self, Write},
42 hash::{Hash, Hasher},
43 num,
44 ops::Range,
45};
46
47use self::private::ValidLen;
48
49#[derive(Debug)]
58pub struct Field {
59 i: usize,
60 fields: FieldSet,
61}
62
63#[derive(Debug, Eq, PartialEq)]
70pub struct Empty;
71
72pub struct FieldSet {
84 names: &'static [&'static str],
86 callsite: callsite::Identifier,
88}
89
90pub struct ValueSet<'a> {
92 values: &'a [(&'a Field, Option<&'a (dyn Value + 'a)>)],
93 fields: &'a FieldSet,
94}
95
96#[derive(Debug)]
98pub struct Iter {
99 idxs: Range<usize>,
100 fields: FieldSet,
101}
102
103pub trait Visit {
192 fn record_f64(&mut self, field: &Field, value: f64) {
194 self.record_debug(field, &value)
195 }
196
197 fn record_i64(&mut self, field: &Field, value: i64) {
199 self.record_debug(field, &value)
200 }
201
202 fn record_u64(&mut self, field: &Field, value: u64) {
204 self.record_debug(field, &value)
205 }
206
207 fn record_i128(&mut self, field: &Field, value: i128) {
209 self.record_debug(field, &value)
210 }
211
212 fn record_u128(&mut self, field: &Field, value: u128) {
214 self.record_debug(field, &value)
215 }
216
217 fn record_bool(&mut self, field: &Field, value: bool) {
219 self.record_debug(field, &value)
220 }
221
222 fn record_str(&mut self, field: &Field, value: &str) {
224 self.record_debug(field, &value)
225 }
226
227 fn record_bytes(&mut self, field: &Field, value: &[u8]) {
229 self.record_debug(field, &HexBytes(value))
230 }
231
232 #[cfg(feature = "std")]
241 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
242 fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) {
243 self.record_debug(field, &DisplayValue(value))
244 }
245
246 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug);
248}
249
250pub trait Value: crate::sealed::Sealed {
258 fn record(&self, key: &Field, visitor: &mut dyn Visit);
260}
261
262#[derive(Clone)]
267pub struct DisplayValue<T: fmt::Display>(T);
268
269#[derive(Clone)]
271pub struct DebugValue<T: fmt::Debug>(T);
272
273pub fn display<T>(t: T) -> DisplayValue<T>
276where
277 T: fmt::Display,
278{
279 DisplayValue(t)
280}
281
282pub fn debug<T>(t: T) -> DebugValue<T>
285where
286 T: fmt::Debug,
287{
288 DebugValue(t)
289}
290
291struct HexBytes<'a>(&'a [u8]);
292
293impl fmt::Debug for HexBytes<'_> {
294 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295 f.write_char('[')?;
296
297 let mut bytes = self.0.iter();
298
299 if let Some(byte) = bytes.next() {
300 f.write_fmt(format_args!("{byte:02x}"))?;
301 }
302
303 for byte in bytes {
304 f.write_fmt(format_args!(" {byte:02x}"))?;
305 }
306
307 f.write_char(']')
308 }
309}
310
311impl Visit for fmt::DebugStruct<'_, '_> {
314 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
315 self.field(field.name(), value);
316 }
317}
318
319impl Visit for fmt::DebugMap<'_, '_> {
320 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
321 self.entry(&format_args!("{}", field), value);
322 }
323}
324
325impl<F> Visit for F
326where
327 F: FnMut(&Field, &dyn fmt::Debug),
328{
329 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
330 (self)(field, value)
331 }
332}
333
334macro_rules! impl_values {
337 ( $( $record:ident( $( $whatever:tt)+ ) ),+ ) => {
338 $(
339 impl_value!{ $record( $( $whatever )+ ) }
340 )+
341 }
342}
343
344macro_rules! ty_to_nonzero {
345 (u8) => {
346 NonZeroU8
347 };
348 (u16) => {
349 NonZeroU16
350 };
351 (u32) => {
352 NonZeroU32
353 };
354 (u64) => {
355 NonZeroU64
356 };
357 (u128) => {
358 NonZeroU128
359 };
360 (usize) => {
361 NonZeroUsize
362 };
363 (i8) => {
364 NonZeroI8
365 };
366 (i16) => {
367 NonZeroI16
368 };
369 (i32) => {
370 NonZeroI32
371 };
372 (i64) => {
373 NonZeroI64
374 };
375 (i128) => {
376 NonZeroI128
377 };
378 (isize) => {
379 NonZeroIsize
380 };
381}
382
383macro_rules! impl_one_value {
384 (f32, $op:expr, $record:ident) => {
385 impl_one_value!(normal, f32, $op, $record);
386 };
387 (f64, $op:expr, $record:ident) => {
388 impl_one_value!(normal, f64, $op, $record);
389 };
390 (bool, $op:expr, $record:ident) => {
391 impl_one_value!(normal, bool, $op, $record);
392 };
393 ($value_ty:tt, $op:expr, $record:ident) => {
394 impl_one_value!(normal, $value_ty, $op, $record);
395 impl_one_value!(nonzero, $value_ty, $op, $record);
396 };
397 (normal, $value_ty:tt, $op:expr, $record:ident) => {
398 impl $crate::sealed::Sealed for $value_ty {}
399 impl $crate::field::Value for $value_ty {
400 fn record(&self, key: &$crate::field::Field, visitor: &mut dyn $crate::field::Visit) {
401 #[allow(clippy::redundant_closure_call)]
405 visitor.$record(key, $op(*self))
406 }
407 }
408 };
409 (nonzero, $value_ty:tt, $op:expr, $record:ident) => {
410 #[allow(clippy::useless_attribute, unused)]
416 use num::*;
417 impl $crate::sealed::Sealed for ty_to_nonzero!($value_ty) {}
418 impl $crate::field::Value for ty_to_nonzero!($value_ty) {
419 fn record(&self, key: &$crate::field::Field, visitor: &mut dyn $crate::field::Visit) {
420 #[allow(clippy::redundant_closure_call)]
424 visitor.$record(key, $op(self.get()))
425 }
426 }
427 };
428}
429
430macro_rules! impl_value {
431 ( $record:ident( $( $value_ty:tt ),+ ) ) => {
432 $(
433 impl_one_value!($value_ty, |this: $value_ty| this, $record);
434 )+
435 };
436 ( $record:ident( $( $value_ty:tt ),+ as $as_ty:ty) ) => {
437 $(
438 impl_one_value!($value_ty, |this: $value_ty| this as $as_ty, $record);
439 )+
440 };
441}
442
443impl_values! {
446 record_u64(u64),
447 record_u64(usize, u32, u16, u8 as u64),
448 record_i64(i64),
449 record_i64(isize, i32, i16, i8 as i64),
450 record_u128(u128),
451 record_i128(i128),
452 record_bool(bool),
453 record_f64(f64, f32 as f64)
454}
455
456impl<T: crate::sealed::Sealed> crate::sealed::Sealed for Wrapping<T> {}
457impl<T: crate::field::Value> crate::field::Value for Wrapping<T> {
458 fn record(&self, key: &crate::field::Field, visitor: &mut dyn crate::field::Visit) {
459 self.0.record(key, visitor)
460 }
461}
462
463impl crate::sealed::Sealed for str {}
464
465impl Value for str {
466 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
467 visitor.record_str(key, self)
468 }
469}
470
471impl crate::sealed::Sealed for [u8] {}
472
473impl Value for [u8] {
474 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
475 visitor.record_bytes(key, self)
476 }
477}
478
479#[cfg(feature = "std")]
480impl crate::sealed::Sealed for dyn std::error::Error + 'static {}
481
482#[cfg(feature = "std")]
483#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
484impl Value for dyn std::error::Error + 'static {
485 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
486 visitor.record_error(key, self)
487 }
488}
489
490#[cfg(feature = "std")]
491impl crate::sealed::Sealed for dyn std::error::Error + Send + 'static {}
492
493#[cfg(feature = "std")]
494#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
495impl Value for dyn std::error::Error + Send + 'static {
496 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
497 (self as &dyn std::error::Error).record(key, visitor)
498 }
499}
500
501#[cfg(feature = "std")]
502impl crate::sealed::Sealed for dyn std::error::Error + Sync + 'static {}
503
504#[cfg(feature = "std")]
505#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
506impl Value for dyn std::error::Error + Sync + 'static {
507 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
508 (self as &dyn std::error::Error).record(key, visitor)
509 }
510}
511
512#[cfg(feature = "std")]
513impl crate::sealed::Sealed for dyn std::error::Error + Send + Sync + 'static {}
514
515#[cfg(feature = "std")]
516#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
517impl Value for dyn std::error::Error + Send + Sync + 'static {
518 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
519 (self as &dyn std::error::Error).record(key, visitor)
520 }
521}
522
523impl<'a, T: ?Sized> crate::sealed::Sealed for &'a T where T: Value + crate::sealed::Sealed + 'a {}
524
525impl<'a, T: ?Sized> Value for &'a T
526where
527 T: Value + 'a,
528{
529 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
530 (*self).record(key, visitor)
531 }
532}
533
534impl<'a, T: ?Sized> crate::sealed::Sealed for &'a mut T where T: Value + crate::sealed::Sealed + 'a {}
535
536impl<'a, T: ?Sized> Value for &'a mut T
537where
538 T: Value + 'a,
539{
540 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
541 T::record(self, key, visitor)
544 }
545}
546
547impl crate::sealed::Sealed for fmt::Arguments<'_> {}
548
549impl Value for fmt::Arguments<'_> {
550 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
551 visitor.record_debug(key, self)
552 }
553}
554
555#[cfg(feature = "alloc")]
556impl<T: ?Sized> crate::sealed::Sealed for alloc::boxed::Box<T> where T: Value {}
557
558#[cfg(feature = "alloc")]
559#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
560impl<T: ?Sized> Value for alloc::boxed::Box<T>
561where
562 T: Value,
563{
564 #[inline]
565 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
566 self.as_ref().record(key, visitor)
567 }
568}
569
570#[cfg(feature = "alloc")]
571#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
572impl crate::sealed::Sealed for alloc::string::String {}
573
574#[cfg(feature = "alloc")]
575#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
576impl Value for alloc::string::String {
577 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
578 visitor.record_str(key, self.as_str())
579 }
580}
581
582impl fmt::Debug for dyn Value {
583 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
584 struct NullCallsite;
587 static NULL_CALLSITE: NullCallsite = NullCallsite;
588 impl crate::callsite::Callsite for NullCallsite {
589 fn set_interest(&self, _: crate::collect::Interest) {
590 unreachable!("you somehow managed to register the null callsite?")
591 }
592
593 fn metadata(&self) -> &crate::Metadata<'_> {
594 unreachable!("you somehow managed to access the null callsite?")
595 }
596 }
597
598 static FIELD: Field = Field {
599 i: 0,
600 fields: FieldSet::new(&[], crate::identify_callsite!(&NULL_CALLSITE)),
601 };
602
603 let mut res = Ok(());
604 self.record(&FIELD, &mut |_: &Field, val: &dyn fmt::Debug| {
605 res = write!(f, "{:?}", val);
606 });
607 res
608 }
609}
610
611impl fmt::Display for dyn Value {
612 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
613 fmt::Debug::fmt(self, f)
614 }
615}
616
617impl<T: fmt::Display> crate::sealed::Sealed for DisplayValue<T> {}
620
621impl<T> Value for DisplayValue<T>
622where
623 T: fmt::Display,
624{
625 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
626 visitor.record_debug(key, self)
627 }
628}
629
630impl<T: fmt::Display> fmt::Debug for DisplayValue<T> {
631 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
632 fmt::Display::fmt(self, f)
633 }
634}
635
636impl<T: fmt::Display> fmt::Display for DisplayValue<T> {
637 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
638 self.0.fmt(f)
639 }
640}
641
642impl<T: fmt::Debug> crate::sealed::Sealed for DebugValue<T> {}
645
646impl<T: fmt::Debug> Value for DebugValue<T>
647where
648 T: fmt::Debug,
649{
650 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
651 visitor.record_debug(key, &self.0)
652 }
653}
654
655impl<T: fmt::Debug> fmt::Debug for DebugValue<T> {
656 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
657 self.0.fmt(f)
658 }
659}
660
661impl crate::sealed::Sealed for Empty {}
662impl Value for Empty {
663 #[inline]
664 fn record(&self, _: &Field, _: &mut dyn Visit) {}
665}
666
667impl Field {
670 #[inline]
676 pub fn callsite(&self) -> callsite::Identifier {
677 self.fields.callsite()
678 }
679
680 pub fn name(&self) -> &'static str {
682 self.fields.names[self.i]
683 }
684
685 pub fn index(&self) -> usize {
687 self.i
688 }
689}
690
691impl fmt::Display for Field {
692 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
693 f.pad(self.name())
694 }
695}
696
697impl AsRef<str> for Field {
698 fn as_ref(&self) -> &str {
699 self.name()
700 }
701}
702
703impl PartialEq for Field {
704 fn eq(&self, other: &Self) -> bool {
705 self.callsite() == other.callsite() && self.i == other.i
706 }
707}
708
709impl Eq for Field {}
710
711impl Hash for Field {
712 fn hash<H>(&self, state: &mut H)
713 where
714 H: Hasher,
715 {
716 self.callsite().hash(state);
717 self.i.hash(state);
718 }
719}
720
721impl Clone for Field {
722 fn clone(&self) -> Self {
723 Field {
724 i: self.i,
725 fields: FieldSet {
726 names: self.fields.names,
727 callsite: self.fields.callsite(),
728 },
729 }
730 }
731}
732
733impl FieldSet {
736 pub const fn new(names: &'static [&'static str], callsite: callsite::Identifier) -> Self {
738 Self { names, callsite }
739 }
740
741 #[inline]
747 pub(crate) fn callsite(&self) -> callsite::Identifier {
748 callsite::Identifier(self.callsite.0)
749 }
750
751 pub fn field<Q>(&self, name: &Q) -> Option<Field>
755 where
756 Q: Borrow<str> + ?Sized,
757 {
758 let name = &name.borrow();
759 self.names.iter().position(|f| f == name).map(|i| Field {
760 i,
761 fields: FieldSet {
762 names: self.names,
763 callsite: self.callsite(),
764 },
765 })
766 }
767
768 pub fn contains(&self, field: &Field) -> bool {
780 field.callsite() == self.callsite() && field.i <= self.len()
781 }
782
783 #[inline]
785 pub fn iter(&self) -> Iter {
786 let idxs = 0..self.len();
787 Iter {
788 idxs,
789 fields: FieldSet {
790 names: self.names,
791 callsite: self.callsite(),
792 },
793 }
794 }
795
796 #[doc(hidden)]
798 pub fn value_set<'v, V>(&'v self, values: &'v V) -> ValueSet<'v>
799 where
800 V: ValidLen<'v>,
801 {
802 ValueSet {
803 fields: self,
804 values: values.borrow(),
805 }
806 }
807
808 #[inline]
810 pub fn len(&self) -> usize {
811 self.names.len()
812 }
813
814 #[inline]
816 pub fn is_empty(&self) -> bool {
817 self.names.is_empty()
818 }
819}
820
821impl IntoIterator for &FieldSet {
822 type IntoIter = Iter;
823 type Item = Field;
824 #[inline]
825 fn into_iter(self) -> Self::IntoIter {
826 self.iter()
827 }
828}
829
830impl fmt::Debug for FieldSet {
831 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
832 f.debug_struct("FieldSet")
833 .field("names", &self.names)
834 .field("callsite", &self.callsite)
835 .finish()
836 }
837}
838
839impl fmt::Display for FieldSet {
840 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
841 f.debug_set()
842 .entries(self.names.iter().map(display))
843 .finish()
844 }
845}
846
847impl Eq for FieldSet {}
848
849impl PartialEq for FieldSet {
850 fn eq(&self, other: &Self) -> bool {
851 if core::ptr::eq(&self, &other) {
852 true
853 } else if cfg!(not(debug_assertions)) {
854 self.callsite == other.callsite
857 } else {
858 let Self {
865 names: lhs_names,
866 callsite: lhs_callsite,
867 } = self;
868
869 let Self {
870 names: rhs_names,
871 callsite: rhs_callsite,
872 } = &other;
873
874 lhs_callsite == rhs_callsite && lhs_names == rhs_names
877 }
878 }
879}
880
881impl Iterator for Iter {
884 type Item = Field;
885 #[inline]
886 fn next(&mut self) -> Option<Field> {
887 let i = self.idxs.next()?;
888 Some(Field {
889 i,
890 fields: FieldSet {
891 names: self.fields.names,
892 callsite: self.fields.callsite(),
893 },
894 })
895 }
896}
897
898impl ValueSet<'_> {
901 #[inline]
907 pub fn callsite(&self) -> callsite::Identifier {
908 self.fields.callsite()
909 }
910
911 pub fn record(&self, visitor: &mut dyn Visit) {
915 let my_callsite = self.callsite();
916 for (field, value) in self.values {
917 if field.callsite() != my_callsite {
918 continue;
919 }
920 if let Some(value) = value {
921 value.record(field, visitor);
922 }
923 }
924 }
925
926 pub fn len(&self) -> usize {
932 let my_callsite = self.callsite();
933 self.values
934 .iter()
935 .filter(|(field, _)| field.callsite() == my_callsite)
936 .count()
937 }
938
939 pub(crate) fn contains(&self, field: &Field) -> bool {
941 field.callsite() == self.callsite()
942 && self
943 .values
944 .iter()
945 .any(|(key, val)| *key == field && val.is_some())
946 }
947
948 pub fn is_empty(&self) -> bool {
950 let my_callsite = self.callsite();
951 self.values
952 .iter()
953 .all(|(key, val)| val.is_none() || key.callsite() != my_callsite)
954 }
955
956 pub(crate) fn field_set(&self) -> &FieldSet {
957 self.fields
958 }
959}
960
961impl fmt::Debug for ValueSet<'_> {
962 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
963 self.values
964 .iter()
965 .fold(&mut f.debug_struct("ValueSet"), |dbg, (key, v)| {
966 if let Some(val) = v {
967 val.record(key, dbg);
968 }
969 dbg
970 })
971 .field("callsite", &self.callsite())
972 .finish()
973 }
974}
975
976impl fmt::Display for ValueSet<'_> {
977 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
978 self.values
979 .iter()
980 .fold(&mut f.debug_map(), |dbg, (key, v)| {
981 if let Some(val) = v {
982 val.record(key, dbg);
983 }
984 dbg
985 })
986 .finish()
987 }
988}
989
990mod private {
993 use super::*;
994
995 pub trait ValidLen<'a>: Borrow<[(&'a Field, Option<&'a (dyn Value + 'a)>)]> {}
997
998 impl<'a, const N: usize> ValidLen<'a> for [(&'a Field, Option<&'a (dyn Value + 'a)>); N] {}
999}
1000
1001#[cfg(test)]
1002mod test {
1003 use super::*;
1004 use crate::metadata::{Kind, Level, Metadata};
1005
1006 struct TestCallsite1();
1008 static TEST_CALLSITE_1: TestCallsite1 = TestCallsite1();
1009 static TEST_META_1: Metadata<'static> = metadata! {
1010 name: "field_test1",
1011 target: module_path!(),
1012 level: Level::INFO,
1013 fields: &["foo", "bar", "baz"],
1014 callsite: &TEST_CALLSITE_1,
1015 kind: Kind::SPAN,
1016 };
1017
1018 impl crate::callsite::Callsite for TestCallsite1 {
1019 fn set_interest(&self, _: crate::collect::Interest) {
1020 unimplemented!()
1021 }
1022
1023 fn metadata(&self) -> &Metadata<'_> {
1024 &TEST_META_1
1025 }
1026 }
1027
1028 struct TestCallsite2();
1029 static TEST_CALLSITE_2: TestCallsite2 = TestCallsite2();
1030 static TEST_META_2: Metadata<'static> = metadata! {
1031 name: "field_test2",
1032 target: module_path!(),
1033 level: Level::INFO,
1034 fields: &["foo", "bar", "baz"],
1035 callsite: &TEST_CALLSITE_2,
1036 kind: Kind::SPAN,
1037 };
1038
1039 impl crate::callsite::Callsite for TestCallsite2 {
1040 fn set_interest(&self, _: crate::collect::Interest) {
1041 unimplemented!()
1042 }
1043
1044 fn metadata(&self) -> &Metadata<'_> {
1045 &TEST_META_2
1046 }
1047 }
1048
1049 #[test]
1050 fn value_set_with_no_values_is_empty() {
1051 let fields = TEST_META_1.fields();
1052 let values = &[
1053 (&fields.field("foo").unwrap(), None),
1054 (&fields.field("bar").unwrap(), None),
1055 (&fields.field("baz").unwrap(), None),
1056 ];
1057 let valueset = fields.value_set(values);
1058 assert!(valueset.is_empty());
1059 }
1060
1061 #[test]
1062 fn index_of_field_in_fieldset_is_correct() {
1063 let fields = TEST_META_1.fields();
1064 let foo = fields.field("foo").unwrap();
1065 assert_eq!(foo.index(), 0);
1066 let bar = fields.field("bar").unwrap();
1067 assert_eq!(bar.index(), 1);
1068 let baz = fields.field("baz").unwrap();
1069 assert_eq!(baz.index(), 2);
1070 }
1071
1072 #[test]
1073 fn empty_value_set_is_empty() {
1074 let fields = TEST_META_1.fields();
1075 let valueset = fields.value_set(&[]);
1076 assert!(valueset.is_empty());
1077 }
1078
1079 #[test]
1080 fn value_sets_with_fields_from_other_callsites_are_empty() {
1081 let fields = TEST_META_1.fields();
1082 let values = &[
1083 (&fields.field("foo").unwrap(), Some(&1 as &dyn Value)),
1084 (&fields.field("bar").unwrap(), Some(&2 as &dyn Value)),
1085 (&fields.field("baz").unwrap(), Some(&3 as &dyn Value)),
1086 ];
1087 let valueset = TEST_META_2.fields().value_set(values);
1088 assert!(valueset.is_empty())
1089 }
1090
1091 #[test]
1092 fn sparse_value_sets_are_not_empty() {
1093 let fields = TEST_META_1.fields();
1094 let values = &[
1095 (&fields.field("foo").unwrap(), None),
1096 (&fields.field("bar").unwrap(), Some(&57 as &dyn Value)),
1097 (&fields.field("baz").unwrap(), None),
1098 ];
1099 let valueset = fields.value_set(values);
1100 assert!(!valueset.is_empty());
1101 }
1102
1103 #[test]
1104 fn fields_from_other_callsets_are_skipped() {
1105 let fields = TEST_META_1.fields();
1106 let values = &[
1107 (&fields.field("foo").unwrap(), None),
1108 (
1109 &TEST_META_2.fields().field("bar").unwrap(),
1110 Some(&57 as &dyn Value),
1111 ),
1112 (&fields.field("baz").unwrap(), None),
1113 ];
1114
1115 struct MyVisitor;
1116 impl Visit for MyVisitor {
1117 fn record_debug(&mut self, field: &Field, _: &dyn (core::fmt::Debug)) {
1118 assert_eq!(field.callsite(), TEST_META_1.callsite())
1119 }
1120 }
1121 let valueset = fields.value_set(values);
1122 valueset.record(&mut MyVisitor);
1123 }
1124
1125 #[test]
1126 fn empty_fields_are_skipped() {
1127 let fields = TEST_META_1.fields();
1128 let values = &[
1129 (&fields.field("foo").unwrap(), Some(&Empty as &dyn Value)),
1130 (&fields.field("bar").unwrap(), Some(&57 as &dyn Value)),
1131 (&fields.field("baz").unwrap(), Some(&Empty as &dyn Value)),
1132 ];
1133
1134 struct MyVisitor;
1135 impl Visit for MyVisitor {
1136 fn record_debug(&mut self, field: &Field, _: &dyn (core::fmt::Debug)) {
1137 assert_eq!(field.name(), "bar")
1138 }
1139 }
1140 let valueset = fields.value_set(values);
1141 valueset.record(&mut MyVisitor);
1142 }
1143
1144 #[test]
1145 #[cfg(feature = "std")]
1146 fn record_debug_fn() {
1147 let fields = TEST_META_1.fields();
1148 let values = &[
1149 (&fields.field("foo").unwrap(), Some(&1 as &dyn Value)),
1150 (&fields.field("bar").unwrap(), Some(&2 as &dyn Value)),
1151 (&fields.field("baz").unwrap(), Some(&3 as &dyn Value)),
1152 ];
1153 let valueset = fields.value_set(values);
1154 let mut result = String::new();
1155 valueset.record(&mut |_: &Field, value: &dyn fmt::Debug| {
1156 use core::fmt::Write;
1157 write!(&mut result, "{:?}", value).unwrap();
1158 });
1159 assert_eq!(result, String::from("123"));
1160 }
1161
1162 #[test]
1163 #[cfg(feature = "std")]
1164 fn record_error() {
1165 let fields = TEST_META_1.fields();
1166 let err: Box<dyn std::error::Error + Send + Sync + 'static> =
1167 std::io::Error::new(std::io::ErrorKind::Other, "lol").into();
1168 let values = &[
1169 (&fields.field("foo").unwrap(), Some(&err as &dyn Value)),
1170 (&fields.field("bar").unwrap(), Some(&Empty as &dyn Value)),
1171 (&fields.field("baz").unwrap(), Some(&Empty as &dyn Value)),
1172 ];
1173 let valueset = fields.value_set(values);
1174 let mut result = String::new();
1175 valueset.record(&mut |_: &Field, value: &dyn fmt::Debug| {
1176 use core::fmt::Write;
1177 write!(&mut result, "{:?}", value).unwrap();
1178 });
1179 assert_eq!(result, format!("{}", err));
1180 }
1181
1182 #[test]
1183 fn record_bytes() {
1184 let fields = TEST_META_1.fields();
1185 let first = &b"abc"[..];
1186 let second: &[u8] = &[192, 255, 238];
1187 let values = &[
1188 (&fields.field("foo").unwrap(), Some(&first as &dyn Value)),
1189 (&fields.field("bar").unwrap(), Some(&" " as &dyn Value)),
1190 (&fields.field("baz").unwrap(), Some(&second as &dyn Value)),
1191 ];
1192 let valueset = fields.value_set(values);
1193 let mut result = String::new();
1194 valueset.record(&mut |_: &Field, value: &dyn fmt::Debug| {
1195 use core::fmt::Write;
1196 write!(&mut result, "{:?}", value).unwrap();
1197 });
1198 assert_eq!(result, format!("{}", r#"[61 62 63]" "[c0 ff ee]"#));
1199 }
1200}