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) 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 #[inline]
954 pub fn len(&self) -> usize {
955 self.names.len()
956 }
957
958 #[inline]
960 pub fn is_empty(&self) -> bool {
961 self.names.is_empty()
962 }
963}
964
965impl IntoIterator for &FieldSet {
966 type IntoIter = Iter;
967 type Item = Field;
968 #[inline]
969 fn into_iter(self) -> Self::IntoIter {
970 self.iter()
971 }
972}
973
974impl fmt::Debug for FieldSet {
975 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
976 f.debug_struct("FieldSet")
977 .field("names", &self.names)
978 .field("callsite", &self.callsite)
979 .finish()
980 }
981}
982
983impl fmt::Display for FieldSet {
984 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
985 f.debug_set()
986 .entries(self.names.iter().map(display))
987 .finish()
988 }
989}
990
991impl Eq for FieldSet {}
992
993impl PartialEq for FieldSet {
994 fn eq(&self, other: &Self) -> bool {
995 if core::ptr::eq(&self, &other) {
996 true
997 } else if cfg!(not(debug_assertions)) {
998 self.callsite == other.callsite
1001 } else {
1002 let Self {
1009 names: lhs_names,
1010 callsite: lhs_callsite,
1011 } = self;
1012
1013 let Self {
1014 names: rhs_names,
1015 callsite: rhs_callsite,
1016 } = &other;
1017
1018 lhs_callsite == rhs_callsite && lhs_names == rhs_names
1021 }
1022 }
1023}
1024
1025impl Iterator for Iter {
1028 type Item = Field;
1029 #[inline]
1030 fn next(&mut self) -> Option<Field> {
1031 let i = self.idxs.next()?;
1032 Some(Field {
1033 i,
1034 fields: FieldSet {
1035 names: self.fields.names,
1036 callsite: self.fields.callsite(),
1037 },
1038 })
1039 }
1040}
1041
1042impl ValueSet<'_> {
1045 #[inline]
1051 pub fn callsite(&self) -> callsite::Identifier {
1052 self.fields.callsite()
1053 }
1054
1055 pub fn record(&self, visitor: &mut dyn Visit) {
1059 match self.values {
1060 Values::Explicit(values) => {
1061 let my_callsite = self.callsite();
1062 for (field, value) in values {
1063 if field.callsite() != my_callsite {
1064 continue;
1065 }
1066 if let Some(value) = *value {
1067 value.record(field, visitor);
1068 }
1069 }
1070 }
1071 Values::All(values) => {
1072 for (field, value) in self.fields.iter().zip(values.iter()) {
1073 if let Some(value) = *value {
1074 value.record(&field, visitor);
1075 }
1076 }
1077 }
1078 }
1079 }
1080
1081 pub fn len(&self) -> usize {
1087 match self.values {
1088 Values::Explicit(values) => {
1089 let my_callsite = self.callsite();
1090 values
1091 .iter()
1092 .filter(|(field, _)| field.callsite() == my_callsite)
1093 .count()
1094 }
1095 Values::All(values) => values.len(),
1096 }
1097 }
1098
1099 pub(crate) fn contains(&self, field: &Field) -> bool {
1101 if field.callsite() != self.callsite() {
1102 return false;
1103 }
1104 match self.values {
1105 Values::Explicit(values) => values
1106 .iter()
1107 .any(|(key, val)| *key == field && val.is_some()),
1108 Values::All(values) => values[field.i].is_some(),
1109 }
1110 }
1111
1112 pub fn is_empty(&self) -> bool {
1114 match self.values {
1115 Values::All(values) => values.iter().all(|v| v.is_none()),
1116 Values::Explicit(values) => {
1117 let my_callsite = self.callsite();
1118 values
1119 .iter()
1120 .all(|(key, val)| val.is_none() || key.callsite() != my_callsite)
1121 }
1122 }
1123 }
1124
1125 pub(crate) fn field_set(&self) -> &FieldSet {
1126 self.fields
1127 }
1128}
1129
1130impl fmt::Debug for ValueSet<'_> {
1131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1132 let mut s = f.debug_struct("ValueSet");
1133 self.record(&mut s);
1134 s.field("callsite", &self.callsite()).finish()
1135 }
1136}
1137
1138impl fmt::Display for ValueSet<'_> {
1139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1140 let mut s = f.debug_map();
1141 self.record(&mut s);
1142 s.finish()
1143 }
1144}
1145
1146mod private {
1149 use super::*;
1150
1151 pub trait ValidLen<'a>: Borrow<[(&'a Field, Option<&'a (dyn Value + 'a)>)]> {}
1153
1154 impl<'a, const N: usize> ValidLen<'a> for [(&'a Field, Option<&'a (dyn Value + 'a)>); N] {}
1155}
1156
1157#[cfg(test)]
1158mod test {
1159 use alloc::{borrow::ToOwned, boxed::Box, string::String};
1160 use std::format;
1161
1162 use super::*;
1163 use crate::metadata::{Kind, Level, Metadata};
1164
1165 struct TestCallsite1 {
1167 _unused: u8,
1168 }
1169 static TEST_CALLSITE_1: TestCallsite1 = TestCallsite1 { _unused: 0 };
1170 static TEST_META_1: Metadata<'static> = metadata! {
1171 name: "field_test1",
1172 target: module_path!(),
1173 level: Level::INFO,
1174 fields: &["foo", "bar", "baz"],
1175 callsite: &TEST_CALLSITE_1,
1176 kind: Kind::SPAN,
1177 };
1178
1179 impl crate::callsite::Callsite for TestCallsite1 {
1180 fn set_interest(&self, _: crate::subscriber::Interest) {
1181 unimplemented!()
1182 }
1183
1184 fn metadata(&self) -> &Metadata<'_> {
1185 &TEST_META_1
1186 }
1187 }
1188
1189 struct TestCallsite2 {
1190 _unused: u8,
1191 }
1192 static TEST_CALLSITE_2: TestCallsite2 = TestCallsite2 { _unused: 0 };
1193 static TEST_META_2: Metadata<'static> = metadata! {
1194 name: "field_test2",
1195 target: module_path!(),
1196 level: Level::INFO,
1197 fields: &["foo", "bar", "baz"],
1198 callsite: &TEST_CALLSITE_2,
1199 kind: Kind::SPAN,
1200 };
1201
1202 impl crate::callsite::Callsite for TestCallsite2 {
1203 fn set_interest(&self, _: crate::subscriber::Interest) {
1204 unimplemented!()
1205 }
1206
1207 fn metadata(&self) -> &Metadata<'_> {
1208 &TEST_META_2
1209 }
1210 }
1211
1212 #[test]
1213 fn value_set_with_no_values_is_empty() {
1214 let fields = TEST_META_1.fields();
1215 let values = &[
1216 (&fields.field("foo").unwrap(), None),
1217 (&fields.field("bar").unwrap(), None),
1218 (&fields.field("baz").unwrap(), None),
1219 ];
1220 let valueset = fields.value_set(values);
1221 assert!(valueset.is_empty());
1222 }
1223
1224 #[test]
1225 fn index_of_field_in_fieldset_is_correct() {
1226 let fields = TEST_META_1.fields();
1227 let foo = fields.field("foo").unwrap();
1228 assert_eq!(foo.index(), 0);
1229 let bar = fields.field("bar").unwrap();
1230 assert_eq!(bar.index(), 1);
1231 let baz = fields.field("baz").unwrap();
1232 assert_eq!(baz.index(), 2);
1233 }
1234
1235 #[test]
1236 fn empty_value_set_is_empty() {
1237 let fields = TEST_META_1.fields();
1238 let valueset = fields.value_set(&[]);
1239 assert!(valueset.is_empty());
1240 }
1241
1242 #[test]
1243 fn value_sets_with_fields_from_other_callsites_are_empty() {
1244 let fields = TEST_META_1.fields();
1245 let values = &[
1246 (&fields.field("foo").unwrap(), Some(&1 as &dyn Value)),
1247 (&fields.field("bar").unwrap(), Some(&2 as &dyn Value)),
1248 (&fields.field("baz").unwrap(), Some(&3 as &dyn Value)),
1249 ];
1250 let valueset = TEST_META_2.fields().value_set(values);
1251 assert!(valueset.is_empty())
1252 }
1253
1254 #[test]
1255 fn sparse_value_sets_are_not_empty() {
1256 let fields = TEST_META_1.fields();
1257 let values = &[
1258 (&fields.field("foo").unwrap(), None),
1259 (&fields.field("bar").unwrap(), Some(&57 as &dyn Value)),
1260 (&fields.field("baz").unwrap(), None),
1261 ];
1262 let valueset = fields.value_set(values);
1263 assert!(!valueset.is_empty());
1264 }
1265
1266 #[test]
1267 fn fields_from_other_callsets_are_skipped() {
1268 let fields = TEST_META_1.fields();
1269 let values = &[
1270 (&fields.field("foo").unwrap(), None),
1271 (
1272 &TEST_META_2.fields().field("bar").unwrap(),
1273 Some(&57 as &dyn Value),
1274 ),
1275 (&fields.field("baz").unwrap(), None),
1276 ];
1277
1278 struct MyVisitor;
1279 impl Visit for MyVisitor {
1280 fn record_debug(&mut self, field: &Field, _: &dyn fmt::Debug) {
1281 assert_eq!(field.callsite(), TEST_META_1.callsite())
1282 }
1283 }
1284 let valueset = fields.value_set(values);
1285 valueset.record(&mut MyVisitor);
1286 }
1287
1288 #[test]
1289 fn empty_fields_are_skipped() {
1290 let fields = TEST_META_1.fields();
1291 let values = &[
1292 (&fields.field("foo").unwrap(), Some(&Empty as &dyn Value)),
1293 (&fields.field("bar").unwrap(), Some(&57 as &dyn Value)),
1294 (&fields.field("baz").unwrap(), Some(&Empty as &dyn Value)),
1295 ];
1296
1297 struct MyVisitor;
1298 impl Visit for MyVisitor {
1299 fn record_debug(&mut self, field: &Field, _: &dyn fmt::Debug) {
1300 assert_eq!(field.name(), "bar")
1301 }
1302 }
1303 let valueset = fields.value_set(values);
1304 valueset.record(&mut MyVisitor);
1305 }
1306
1307 #[test]
1308 fn record_debug_fn() {
1309 let fields = TEST_META_1.fields();
1310 let values = &[
1311 (&fields.field("foo").unwrap(), Some(&1 as &dyn Value)),
1312 (&fields.field("bar").unwrap(), Some(&2 as &dyn Value)),
1313 (&fields.field("baz").unwrap(), Some(&3 as &dyn Value)),
1314 ];
1315 let valueset = fields.value_set(values);
1316 let mut result = String::new();
1317 valueset.record(&mut |_: &Field, value: &dyn fmt::Debug| {
1318 use core::fmt::Write;
1319 write!(&mut result, "{:?}", value).unwrap();
1320 });
1321 assert_eq!(result, "123".to_owned());
1322 }
1323
1324 #[test]
1325 #[cfg(feature = "std")]
1326 fn record_error() {
1327 let fields = TEST_META_1.fields();
1328 let err: Box<dyn std::error::Error + Send + Sync + 'static> =
1329 std::io::Error::new(std::io::ErrorKind::Other, "lol").into();
1330 let values = &[
1331 (&fields.field("foo").unwrap(), Some(&err as &dyn Value)),
1332 (&fields.field("bar").unwrap(), Some(&Empty as &dyn Value)),
1333 (&fields.field("baz").unwrap(), Some(&Empty as &dyn Value)),
1334 ];
1335 let valueset = fields.value_set(values);
1336 let mut result = String::new();
1337 valueset.record(&mut |_: &Field, value: &dyn fmt::Debug| {
1338 use core::fmt::Write;
1339 write!(&mut result, "{:?}", value).unwrap();
1340 });
1341 assert_eq!(result, format!("{}", err));
1342 }
1343
1344 #[test]
1345 fn record_bytes() {
1346 let fields = TEST_META_1.fields();
1347 let first = &b"abc"[..];
1348 let second: &[u8] = &[192, 255, 238];
1349 let values = &[
1350 (&fields.field("foo").unwrap(), Some(&first as &dyn Value)),
1351 (&fields.field("bar").unwrap(), Some(&" " as &dyn Value)),
1352 (&fields.field("baz").unwrap(), Some(&second as &dyn Value)),
1353 ];
1354 let valueset = fields.value_set(values);
1355 let mut result = String::new();
1356 valueset.record(&mut |_: &Field, value: &dyn fmt::Debug| {
1357 use core::fmt::Write;
1358 write!(&mut result, "{:?}", value).unwrap();
1359 });
1360 assert_eq!(result, format!("{}", r#"[61 62 63]" "[c0 ff ee]"#));
1361 }
1362}