1use alloc::{boxed::Box, string::String};
114use core::{
115 borrow::Borrow,
116 fmt::{self, Write},
117 hash::{Hash, Hasher},
118 num,
119 ops::Range,
120};
121
122use self::private::ValidLen;
123use crate::callsite;
124
125#[derive(Debug)]
134pub struct Field {
135 i: usize,
136 fields: FieldSet,
137}
138
139#[derive(Debug, Eq, PartialEq)]
146pub struct Empty;
147
148pub struct FieldSet {
160 names: &'static [&'static str],
162 callsite: callsite::Identifier,
164}
165
166pub struct ValueSet<'a> {
168 values: Values<'a>,
169 fields: &'a FieldSet,
170}
171
172enum Values<'a> {
173 Explicit(&'a [(&'a Field, Option<&'a (dyn Value + 'a)>)]),
176 All(&'a [Option<&'a (dyn Value + 'a)>]),
178}
179
180#[derive(Debug)]
182pub struct Iter {
183 idxs: Range<usize>,
184 fields: FieldSet,
185}
186
187pub trait Visit {
276 #[cfg(all(tracing_unstable, feature = "valuable"))]
280 #[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))]
281 fn record_value(&mut self, field: &Field, value: valuable::Value<'_>) {
282 self.record_debug(field, &value)
283 }
284
285 fn record_f64(&mut self, field: &Field, value: f64) {
287 self.record_debug(field, &value)
288 }
289
290 fn record_i64(&mut self, field: &Field, value: i64) {
292 self.record_debug(field, &value)
293 }
294
295 fn record_u64(&mut self, field: &Field, value: u64) {
297 self.record_debug(field, &value)
298 }
299
300 fn record_i128(&mut self, field: &Field, value: i128) {
302 self.record_debug(field, &value)
303 }
304
305 fn record_u128(&mut self, field: &Field, value: u128) {
307 self.record_debug(field, &value)
308 }
309
310 fn record_bool(&mut self, field: &Field, value: bool) {
312 self.record_debug(field, &value)
313 }
314
315 fn record_str(&mut self, field: &Field, value: &str) {
317 self.record_debug(field, &value)
318 }
319
320 fn record_bytes(&mut self, field: &Field, value: &[u8]) {
322 self.record_debug(field, &HexBytes(value))
323 }
324
325 #[cfg(feature = "std")]
334 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
335 fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) {
336 self.record_debug(field, &DisplayValue(value))
337 }
338
339 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug);
341}
342
343pub trait Value: crate::sealed::Sealed {
351 fn record(&self, key: &Field, visitor: &mut dyn Visit);
353}
354
355#[derive(Clone)]
360pub struct DisplayValue<T: fmt::Display>(T);
361
362#[derive(Clone)]
364pub struct DebugValue<T: fmt::Debug>(T);
365
366pub fn display<T>(t: T) -> DisplayValue<T>
369where
370 T: fmt::Display,
371{
372 DisplayValue(t)
373}
374
375pub fn debug<T>(t: T) -> DebugValue<T>
378where
379 T: fmt::Debug,
380{
381 DebugValue(t)
382}
383
384#[cfg(all(tracing_unstable, feature = "valuable"))]
389#[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))]
390pub fn valuable<T>(t: &T) -> valuable::Value<'_>
391where
392 T: valuable::Valuable,
393{
394 t.as_value()
395}
396
397struct HexBytes<'a>(&'a [u8]);
398
399impl fmt::Debug for HexBytes<'_> {
400 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
401 f.write_char('[')?;
402
403 let mut bytes = self.0.iter();
404
405 if let Some(byte) = bytes.next() {
406 f.write_fmt(format_args!("{byte:02x}"))?;
407 }
408
409 for byte in bytes {
410 f.write_fmt(format_args!(" {byte:02x}"))?;
411 }
412
413 f.write_char(']')
414 }
415}
416
417impl Visit for fmt::DebugStruct<'_, '_> {
420 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
421 self.field(field.name(), value);
422 }
423}
424
425impl Visit for fmt::DebugMap<'_, '_> {
426 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
427 self.entry(&format_args!("{}", field), value);
428 }
429}
430
431impl<F> Visit for F
432where
433 F: FnMut(&Field, &dyn fmt::Debug),
434{
435 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
436 (self)(field, value)
437 }
438}
439
440macro_rules! impl_values {
443 ( $( $record:ident( $( $whatever:tt)+ ) ),+ ) => {
444 $(
445 impl_value!{ $record( $( $whatever )+ ) }
446 )+
447 }
448}
449
450macro_rules! ty_to_nonzero {
451 (u8) => {
452 NonZeroU8
453 };
454 (u16) => {
455 NonZeroU16
456 };
457 (u32) => {
458 NonZeroU32
459 };
460 (u64) => {
461 NonZeroU64
462 };
463 (u128) => {
464 NonZeroU128
465 };
466 (usize) => {
467 NonZeroUsize
468 };
469 (i8) => {
470 NonZeroI8
471 };
472 (i16) => {
473 NonZeroI16
474 };
475 (i32) => {
476 NonZeroI32
477 };
478 (i64) => {
479 NonZeroI64
480 };
481 (i128) => {
482 NonZeroI128
483 };
484 (isize) => {
485 NonZeroIsize
486 };
487}
488
489macro_rules! impl_one_value {
490 (f32, $op:expr, $record:ident) => {
491 impl_one_value!(normal, f32, $op, $record);
492 };
493 (f64, $op:expr, $record:ident) => {
494 impl_one_value!(normal, f64, $op, $record);
495 };
496 (bool, $op:expr, $record:ident) => {
497 impl_one_value!(normal, bool, $op, $record);
498 };
499 ($value_ty:tt, $op:expr, $record:ident) => {
500 impl_one_value!(normal, $value_ty, $op, $record);
501 impl_one_value!(nonzero, $value_ty, $op, $record);
502 };
503 (normal, $value_ty:tt, $op:expr, $record:ident) => {
504 impl $crate::sealed::Sealed for $value_ty {}
505 impl $crate::field::Value for $value_ty {
506 fn record(&self, key: &$crate::field::Field, visitor: &mut dyn $crate::field::Visit) {
507 #[allow(clippy::redundant_closure_call)]
511 visitor.$record(key, $op(*self))
512 }
513 }
514 };
515 (nonzero, $value_ty:tt, $op:expr, $record:ident) => {
516 #[allow(clippy::useless_attribute, unused)]
522 use num::*;
523 impl $crate::sealed::Sealed for ty_to_nonzero!($value_ty) {}
524 impl $crate::field::Value for ty_to_nonzero!($value_ty) {
525 fn record(&self, key: &$crate::field::Field, visitor: &mut dyn $crate::field::Visit) {
526 #[allow(clippy::redundant_closure_call)]
530 visitor.$record(key, $op(self.get()))
531 }
532 }
533 };
534}
535
536macro_rules! impl_value {
537 ( $record:ident( $( $value_ty:tt ),+ ) ) => {
538 $(
539 impl_one_value!($value_ty, |this: $value_ty| this, $record);
540 )+
541 };
542 ( $record:ident( $( $value_ty:tt ),+ as $as_ty:ty) ) => {
543 $(
544 impl_one_value!($value_ty, |this: $value_ty| this as $as_ty, $record);
545 )+
546 };
547}
548
549impl_values! {
552 record_u64(u64),
553 record_u64(usize, u32, u16, u8 as u64),
554 record_i64(i64),
555 record_i64(isize, i32, i16, i8 as i64),
556 record_u128(u128),
557 record_i128(i128),
558 record_bool(bool),
559 record_f64(f64, f32 as f64)
560}
561
562impl<T: crate::sealed::Sealed> crate::sealed::Sealed for Wrapping<T> {}
563impl<T: crate::field::Value> crate::field::Value for Wrapping<T> {
564 fn record(&self, key: &crate::field::Field, visitor: &mut dyn crate::field::Visit) {
565 self.0.record(key, visitor)
566 }
567}
568
569impl crate::sealed::Sealed for str {}
570
571impl Value for str {
572 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
573 visitor.record_str(key, self)
574 }
575}
576
577impl crate::sealed::Sealed for [u8] {}
578
579impl Value for [u8] {
580 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
581 visitor.record_bytes(key, self)
582 }
583}
584
585#[cfg(feature = "std")]
586impl crate::sealed::Sealed for dyn std::error::Error + 'static {}
587
588#[cfg(feature = "std")]
589#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
590impl Value for dyn std::error::Error + 'static {
591 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
592 visitor.record_error(key, self)
593 }
594}
595
596#[cfg(feature = "std")]
597impl crate::sealed::Sealed for dyn std::error::Error + Send + 'static {}
598
599#[cfg(feature = "std")]
600#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
601impl Value for dyn std::error::Error + Send + 'static {
602 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
603 (self as &dyn std::error::Error).record(key, visitor)
604 }
605}
606
607#[cfg(feature = "std")]
608impl crate::sealed::Sealed for dyn std::error::Error + Sync + 'static {}
609
610#[cfg(feature = "std")]
611#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
612impl Value for dyn std::error::Error + Sync + 'static {
613 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
614 (self as &dyn std::error::Error).record(key, visitor)
615 }
616}
617
618#[cfg(feature = "std")]
619impl crate::sealed::Sealed for dyn std::error::Error + Send + Sync + 'static {}
620
621#[cfg(feature = "std")]
622#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
623impl Value for dyn std::error::Error + Send + Sync + 'static {
624 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
625 (self as &dyn std::error::Error).record(key, visitor)
626 }
627}
628
629impl<'a, T: ?Sized> crate::sealed::Sealed for &'a T where T: Value + crate::sealed::Sealed + 'a {}
630
631impl<'a, T: ?Sized> Value for &'a T
632where
633 T: Value + 'a,
634{
635 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
636 (*self).record(key, visitor)
637 }
638}
639
640impl<'a, T: ?Sized> crate::sealed::Sealed for &'a mut T where T: Value + crate::sealed::Sealed + 'a {}
641
642impl<'a, T: ?Sized> Value for &'a mut T
643where
644 T: Value + 'a,
645{
646 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
647 T::record(self, key, visitor)
650 }
651}
652
653impl crate::sealed::Sealed for fmt::Arguments<'_> {}
654
655impl Value for fmt::Arguments<'_> {
656 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
657 visitor.record_debug(key, self)
658 }
659}
660
661impl<T: ?Sized> crate::sealed::Sealed for Box<T> where T: Value {}
662
663impl<T: ?Sized> Value for Box<T>
664where
665 T: Value,
666{
667 #[inline]
668 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
669 self.as_ref().record(key, visitor)
670 }
671}
672
673impl crate::sealed::Sealed for String {}
674impl Value for String {
675 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
676 visitor.record_str(key, self.as_str())
677 }
678}
679
680impl fmt::Debug for dyn Value {
681 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
682 struct NullCallsite;
685 static NULL_CALLSITE: NullCallsite = NullCallsite;
686 impl crate::callsite::Callsite for NullCallsite {
687 fn set_interest(&self, _: crate::subscriber::Interest) {
688 unreachable!("you somehow managed to register the null callsite?")
689 }
690
691 fn metadata(&self) -> &crate::Metadata<'_> {
692 unreachable!("you somehow managed to access the null callsite?")
693 }
694 }
695
696 static FIELD: Field = Field {
697 i: 0,
698 fields: FieldSet::new(&[], crate::identify_callsite!(&NULL_CALLSITE)),
699 };
700
701 let mut res = Ok(());
702 self.record(&FIELD, &mut |_: &Field, val: &dyn fmt::Debug| {
703 res = write!(f, "{:?}", val);
704 });
705 res
706 }
707}
708
709impl fmt::Display for dyn Value {
710 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
711 fmt::Debug::fmt(self, f)
712 }
713}
714
715impl<T: fmt::Display> crate::sealed::Sealed for DisplayValue<T> {}
718
719impl<T> Value for DisplayValue<T>
720where
721 T: fmt::Display,
722{
723 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
724 visitor.record_debug(key, self)
725 }
726}
727
728impl<T: fmt::Display> fmt::Debug for DisplayValue<T> {
729 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
730 fmt::Display::fmt(self, f)
731 }
732}
733
734impl<T: fmt::Display> fmt::Display for DisplayValue<T> {
735 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
736 self.0.fmt(f)
737 }
738}
739
740impl<T: fmt::Debug> crate::sealed::Sealed for DebugValue<T> {}
743
744impl<T> Value for DebugValue<T>
745where
746 T: fmt::Debug,
747{
748 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
749 visitor.record_debug(key, &self.0)
750 }
751}
752
753impl<T: fmt::Debug> fmt::Debug for DebugValue<T> {
754 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
755 self.0.fmt(f)
756 }
757}
758
759#[cfg(all(tracing_unstable, feature = "valuable"))]
762impl crate::sealed::Sealed for valuable::Value<'_> {}
763
764#[cfg(all(tracing_unstable, feature = "valuable"))]
765#[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))]
766impl Value for valuable::Value<'_> {
767 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
768 visitor.record_value(key, *self)
769 }
770}
771
772#[cfg(all(tracing_unstable, feature = "valuable"))]
773impl crate::sealed::Sealed for &'_ dyn valuable::Valuable {}
774
775#[cfg(all(tracing_unstable, feature = "valuable"))]
776#[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))]
777impl Value for &'_ dyn valuable::Valuable {
778 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
779 visitor.record_value(key, self.as_value())
780 }
781}
782
783impl crate::sealed::Sealed for Empty {}
784impl Value for Empty {
785 #[inline]
786 fn record(&self, _: &Field, _: &mut dyn Visit) {}
787}
788
789impl<T: Value> crate::sealed::Sealed for Option<T> {}
790
791impl<T: Value> Value for Option<T> {
792 fn record(&self, key: &Field, visitor: &mut dyn Visit) {
793 if let Some(v) = &self {
794 v.record(key, visitor)
795 }
796 }
797}
798
799impl Field {
802 #[inline]
808 pub fn callsite(&self) -> callsite::Identifier {
809 self.fields.callsite()
810 }
811
812 pub fn name(&self) -> &'static str {
814 self.fields.names[self.i]
815 }
816
817 pub fn index(&self) -> usize {
819 self.i
820 }
821}
822
823impl fmt::Display for Field {
824 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
825 f.pad(self.name())
826 }
827}
828
829impl AsRef<str> for Field {
830 fn as_ref(&self) -> &str {
831 self.name()
832 }
833}
834
835impl PartialEq for Field {
836 fn eq(&self, other: &Self) -> bool {
837 self.callsite() == other.callsite() && self.i == other.i
838 }
839}
840
841impl Eq for Field {}
842
843impl Hash for Field {
844 fn hash<H>(&self, state: &mut H)
845 where
846 H: Hasher,
847 {
848 self.callsite().hash(state);
849 self.i.hash(state);
850 }
851}
852
853impl Clone for Field {
854 fn clone(&self) -> Self {
855 Field {
856 i: self.i,
857 fields: FieldSet {
858 names: self.fields.names,
859 callsite: self.fields.callsite(),
860 },
861 }
862 }
863}
864
865impl FieldSet {
868 pub const fn new(names: &'static [&'static str], callsite: callsite::Identifier) -> Self {
870 Self { names, callsite }
871 }
872
873 #[inline]
879 pub(crate) const fn callsite(&self) -> callsite::Identifier {
880 callsite::Identifier(self.callsite.0)
881 }
882
883 pub fn field<Q: Borrow<str> + ?Sized>(&self, name: &Q) -> Option<Field> {
887 let name = &name.borrow();
888 self.names.iter().position(|f| f == name).map(|i| Field {
889 i,
890 fields: FieldSet {
891 names: self.names,
892 callsite: self.callsite(),
893 },
894 })
895 }
896
897 pub fn contains(&self, field: &Field) -> bool {
909 field.callsite() == self.callsite() && field.i <= self.len()
910 }
911
912 #[inline]
914 pub fn iter(&self) -> Iter {
915 let idxs = 0..self.len();
916 Iter {
917 idxs,
918 fields: FieldSet {
919 names: self.names,
920 callsite: self.callsite(),
921 },
922 }
923 }
924
925 #[doc(hidden)]
927 pub fn value_set<'v, V>(&'v self, values: &'v V) -> ValueSet<'v>
928 where
929 V: ValidLen<'v>,
930 {
931 ValueSet {
932 fields: self,
933 values: Values::Explicit(values.borrow()),
934 }
935 }
936
937 #[doc(hidden)]
944 pub fn value_set_all<'v>(&'v self, values: &'v [Option<&'v (dyn Value + 'v)>]) -> ValueSet<'v> {
945 debug_assert_eq!(values.len(), self.len());
946 ValueSet {
947 fields: self,
948 values: Values::All(values),
949 }
950 }
951
952 pub(crate) const fn fake_field(&self) -> Field {
953 Field {
954 i: usize::MAX,
955 fields: FieldSet {
956 names: self.names,
957 callsite: self.callsite(),
958 },
959 }
960 }
961
962 #[inline]
964 pub fn len(&self) -> usize {
965 self.names.len()
966 }
967
968 #[inline]
970 pub fn is_empty(&self) -> bool {
971 self.names.is_empty()
972 }
973}
974
975impl IntoIterator for &FieldSet {
976 type IntoIter = Iter;
977 type Item = Field;
978 #[inline]
979 fn into_iter(self) -> Self::IntoIter {
980 self.iter()
981 }
982}
983
984impl fmt::Debug for FieldSet {
985 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
986 f.debug_struct("FieldSet")
987 .field("names", &self.names)
988 .field("callsite", &self.callsite)
989 .finish()
990 }
991}
992
993impl fmt::Display for FieldSet {
994 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
995 f.debug_set()
996 .entries(self.names.iter().map(display))
997 .finish()
998 }
999}
1000
1001impl Eq for FieldSet {}
1002
1003impl PartialEq for FieldSet {
1004 fn eq(&self, other: &Self) -> bool {
1005 if core::ptr::eq(&self, &other) {
1006 true
1007 } else if cfg!(not(debug_assertions)) {
1008 self.callsite == other.callsite
1011 } else {
1012 let Self {
1019 names: lhs_names,
1020 callsite: lhs_callsite,
1021 } = self;
1022
1023 let Self {
1024 names: rhs_names,
1025 callsite: rhs_callsite,
1026 } = &other;
1027
1028 lhs_callsite == rhs_callsite && lhs_names == rhs_names
1031 }
1032 }
1033}
1034
1035impl Iterator for Iter {
1038 type Item = Field;
1039 #[inline]
1040 fn next(&mut self) -> Option<Field> {
1041 let i = self.idxs.next()?;
1042 Some(Field {
1043 i,
1044 fields: FieldSet {
1045 names: self.fields.names,
1046 callsite: self.fields.callsite(),
1047 },
1048 })
1049 }
1050}
1051
1052impl ValueSet<'_> {
1055 #[inline]
1061 pub fn callsite(&self) -> callsite::Identifier {
1062 self.fields.callsite()
1063 }
1064
1065 pub fn record(&self, visitor: &mut dyn Visit) {
1069 match self.values {
1070 Values::Explicit(values) => {
1071 let my_callsite = self.callsite();
1072 for (field, value) in values {
1073 if field.callsite() != my_callsite {
1074 continue;
1075 }
1076 if let Some(value) = *value {
1077 value.record(field, visitor);
1078 }
1079 }
1080 }
1081 Values::All(values) => {
1082 for (field, value) in self.fields.iter().zip(values.iter()) {
1083 if let Some(value) = *value {
1084 value.record(&field, visitor);
1085 }
1086 }
1087 }
1088 }
1089 }
1090
1091 pub fn len(&self) -> usize {
1097 match self.values {
1098 Values::Explicit(values) => {
1099 let my_callsite = self.callsite();
1100 values
1101 .iter()
1102 .filter(|(field, _)| field.callsite() == my_callsite)
1103 .count()
1104 }
1105 Values::All(values) => values.len(),
1106 }
1107 }
1108
1109 pub(crate) fn contains(&self, field: &Field) -> bool {
1111 if field.callsite() != self.callsite() {
1112 return false;
1113 }
1114 match self.values {
1115 Values::Explicit(values) => values
1116 .iter()
1117 .any(|(key, val)| *key == field && val.is_some()),
1118 Values::All(values) => values[field.i].is_some(),
1119 }
1120 }
1121
1122 pub fn is_empty(&self) -> bool {
1124 match self.values {
1125 Values::All(values) => values.iter().all(|v| v.is_none()),
1126 Values::Explicit(values) => {
1127 let my_callsite = self.callsite();
1128 values
1129 .iter()
1130 .all(|(key, val)| val.is_none() || key.callsite() != my_callsite)
1131 }
1132 }
1133 }
1134
1135 pub(crate) fn field_set(&self) -> &FieldSet {
1136 self.fields
1137 }
1138}
1139
1140impl fmt::Debug for ValueSet<'_> {
1141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1142 let mut s = f.debug_struct("ValueSet");
1143 self.record(&mut s);
1144 s.field("callsite", &self.callsite()).finish()
1145 }
1146}
1147
1148impl fmt::Display for ValueSet<'_> {
1149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1150 let mut s = f.debug_map();
1151 self.record(&mut s);
1152 s.finish()
1153 }
1154}
1155
1156mod private {
1159 use super::*;
1160
1161 pub trait ValidLen<'a>: Borrow<[(&'a Field, Option<&'a (dyn Value + 'a)>)]> {}
1163
1164 impl<'a, const N: usize> ValidLen<'a> for [(&'a Field, Option<&'a (dyn Value + 'a)>); N] {}
1165}
1166
1167#[cfg(test)]
1168mod test {
1169 use alloc::{borrow::ToOwned, boxed::Box, string::String};
1170 use std::format;
1171
1172 use super::*;
1173 use crate::metadata::{Kind, Level, Metadata};
1174
1175 struct TestCallsite1 {
1177 _unused: u8,
1178 }
1179 static TEST_CALLSITE_1: TestCallsite1 = TestCallsite1 { _unused: 0 };
1180 static TEST_META_1: Metadata<'static> = metadata! {
1181 name: "field_test1",
1182 target: module_path!(),
1183 level: Level::INFO,
1184 fields: &["foo", "bar", "baz"],
1185 callsite: &TEST_CALLSITE_1,
1186 kind: Kind::SPAN,
1187 };
1188
1189 impl crate::callsite::Callsite for TestCallsite1 {
1190 fn set_interest(&self, _: crate::subscriber::Interest) {
1191 unimplemented!()
1192 }
1193
1194 fn metadata(&self) -> &Metadata<'_> {
1195 &TEST_META_1
1196 }
1197 }
1198
1199 struct TestCallsite2 {
1200 _unused: u8,
1201 }
1202 static TEST_CALLSITE_2: TestCallsite2 = TestCallsite2 { _unused: 0 };
1203 static TEST_META_2: Metadata<'static> = metadata! {
1204 name: "field_test2",
1205 target: module_path!(),
1206 level: Level::INFO,
1207 fields: &["foo", "bar", "baz"],
1208 callsite: &TEST_CALLSITE_2,
1209 kind: Kind::SPAN,
1210 };
1211
1212 impl crate::callsite::Callsite for TestCallsite2 {
1213 fn set_interest(&self, _: crate::subscriber::Interest) {
1214 unimplemented!()
1215 }
1216
1217 fn metadata(&self) -> &Metadata<'_> {
1218 &TEST_META_2
1219 }
1220 }
1221
1222 #[test]
1223 fn value_set_with_no_values_is_empty() {
1224 let fields = TEST_META_1.fields();
1225 let values = &[
1226 (&fields.field("foo").unwrap(), None),
1227 (&fields.field("bar").unwrap(), None),
1228 (&fields.field("baz").unwrap(), None),
1229 ];
1230 let valueset = fields.value_set(values);
1231 assert!(valueset.is_empty());
1232 }
1233
1234 #[test]
1235 fn index_of_field_in_fieldset_is_correct() {
1236 let fields = TEST_META_1.fields();
1237 let foo = fields.field("foo").unwrap();
1238 assert_eq!(foo.index(), 0);
1239 let bar = fields.field("bar").unwrap();
1240 assert_eq!(bar.index(), 1);
1241 let baz = fields.field("baz").unwrap();
1242 assert_eq!(baz.index(), 2);
1243 }
1244
1245 #[test]
1246 fn empty_value_set_is_empty() {
1247 let fields = TEST_META_1.fields();
1248 let valueset = fields.value_set(&[]);
1249 assert!(valueset.is_empty());
1250 }
1251
1252 #[test]
1253 fn value_sets_with_fields_from_other_callsites_are_empty() {
1254 let fields = TEST_META_1.fields();
1255 let values = &[
1256 (&fields.field("foo").unwrap(), Some(&1 as &dyn Value)),
1257 (&fields.field("bar").unwrap(), Some(&2 as &dyn Value)),
1258 (&fields.field("baz").unwrap(), Some(&3 as &dyn Value)),
1259 ];
1260 let valueset = TEST_META_2.fields().value_set(values);
1261 assert!(valueset.is_empty())
1262 }
1263
1264 #[test]
1265 fn sparse_value_sets_are_not_empty() {
1266 let fields = TEST_META_1.fields();
1267 let values = &[
1268 (&fields.field("foo").unwrap(), None),
1269 (&fields.field("bar").unwrap(), Some(&57 as &dyn Value)),
1270 (&fields.field("baz").unwrap(), None),
1271 ];
1272 let valueset = fields.value_set(values);
1273 assert!(!valueset.is_empty());
1274 }
1275
1276 #[test]
1277 fn fields_from_other_callsets_are_skipped() {
1278 let fields = TEST_META_1.fields();
1279 let values = &[
1280 (&fields.field("foo").unwrap(), None),
1281 (
1282 &TEST_META_2.fields().field("bar").unwrap(),
1283 Some(&57 as &dyn Value),
1284 ),
1285 (&fields.field("baz").unwrap(), None),
1286 ];
1287
1288 struct MyVisitor;
1289 impl Visit for MyVisitor {
1290 fn record_debug(&mut self, field: &Field, _: &dyn fmt::Debug) {
1291 assert_eq!(field.callsite(), TEST_META_1.callsite())
1292 }
1293 }
1294 let valueset = fields.value_set(values);
1295 valueset.record(&mut MyVisitor);
1296 }
1297
1298 #[test]
1299 fn empty_fields_are_skipped() {
1300 let fields = TEST_META_1.fields();
1301 let values = &[
1302 (&fields.field("foo").unwrap(), Some(&Empty as &dyn Value)),
1303 (&fields.field("bar").unwrap(), Some(&57 as &dyn Value)),
1304 (&fields.field("baz").unwrap(), Some(&Empty as &dyn Value)),
1305 ];
1306
1307 struct MyVisitor;
1308 impl Visit for MyVisitor {
1309 fn record_debug(&mut self, field: &Field, _: &dyn fmt::Debug) {
1310 assert_eq!(field.name(), "bar")
1311 }
1312 }
1313 let valueset = fields.value_set(values);
1314 valueset.record(&mut MyVisitor);
1315 }
1316
1317 #[test]
1318 fn record_debug_fn() {
1319 let fields = TEST_META_1.fields();
1320 let values = &[
1321 (&fields.field("foo").unwrap(), Some(&1 as &dyn Value)),
1322 (&fields.field("bar").unwrap(), Some(&2 as &dyn Value)),
1323 (&fields.field("baz").unwrap(), Some(&3 as &dyn Value)),
1324 ];
1325 let valueset = fields.value_set(values);
1326 let mut result = String::new();
1327 valueset.record(&mut |_: &Field, value: &dyn fmt::Debug| {
1328 use core::fmt::Write;
1329 write!(&mut result, "{:?}", value).unwrap();
1330 });
1331 assert_eq!(result, "123".to_owned());
1332 }
1333
1334 #[test]
1335 #[cfg(feature = "std")]
1336 fn record_error() {
1337 let fields = TEST_META_1.fields();
1338 let err: Box<dyn std::error::Error + Send + Sync + 'static> =
1339 std::io::Error::new(std::io::ErrorKind::Other, "lol").into();
1340 let values = &[
1341 (&fields.field("foo").unwrap(), Some(&err as &dyn Value)),
1342 (&fields.field("bar").unwrap(), Some(&Empty as &dyn Value)),
1343 (&fields.field("baz").unwrap(), Some(&Empty as &dyn Value)),
1344 ];
1345 let valueset = fields.value_set(values);
1346 let mut result = String::new();
1347 valueset.record(&mut |_: &Field, value: &dyn fmt::Debug| {
1348 use core::fmt::Write;
1349 write!(&mut result, "{:?}", value).unwrap();
1350 });
1351 assert_eq!(result, format!("{}", err));
1352 }
1353
1354 #[test]
1355 fn record_bytes() {
1356 let fields = TEST_META_1.fields();
1357 let first = &b"abc"[..];
1358 let second: &[u8] = &[192, 255, 238];
1359 let values = &[
1360 (&fields.field("foo").unwrap(), Some(&first as &dyn Value)),
1361 (&fields.field("bar").unwrap(), Some(&" " as &dyn Value)),
1362 (&fields.field("baz").unwrap(), Some(&second as &dyn Value)),
1363 ];
1364 let valueset = fields.value_set(values);
1365 let mut result = String::new();
1366 valueset.record(&mut |_: &Field, value: &dyn fmt::Debug| {
1367 use core::fmt::Write;
1368 write!(&mut result, "{:?}", value).unwrap();
1369 });
1370 assert_eq!(result, format!("{}", r#"[61 62 63]" "[c0 ff ee]"#));
1371 }
1372}