1#![doc(
354 html_logo_url = "https://prev.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
355 html_favicon_url = "https://prev.rust-lang.org/favicon.ico"
356)]
357#![warn(missing_docs)]
358#![deny(missing_debug_implementations, unconditional_recursion)]
359#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
360
361#[cfg(any(
362 all(feature = "max_level_off", feature = "max_level_error"),
363 all(feature = "max_level_off", feature = "max_level_warn"),
364 all(feature = "max_level_off", feature = "max_level_info"),
365 all(feature = "max_level_off", feature = "max_level_debug"),
366 all(feature = "max_level_off", feature = "max_level_trace"),
367 all(feature = "max_level_error", feature = "max_level_warn"),
368 all(feature = "max_level_error", feature = "max_level_info"),
369 all(feature = "max_level_error", feature = "max_level_debug"),
370 all(feature = "max_level_error", feature = "max_level_trace"),
371 all(feature = "max_level_warn", feature = "max_level_info"),
372 all(feature = "max_level_warn", feature = "max_level_debug"),
373 all(feature = "max_level_warn", feature = "max_level_trace"),
374 all(feature = "max_level_info", feature = "max_level_debug"),
375 all(feature = "max_level_info", feature = "max_level_trace"),
376 all(feature = "max_level_debug", feature = "max_level_trace"),
377))]
378compile_error!("multiple max_level_* features set");
379
380#[rustfmt::skip]
381#[cfg(any(
382 all(feature = "release_max_level_off", feature = "release_max_level_error"),
383 all(feature = "release_max_level_off", feature = "release_max_level_warn"),
384 all(feature = "release_max_level_off", feature = "release_max_level_info"),
385 all(feature = "release_max_level_off", feature = "release_max_level_debug"),
386 all(feature = "release_max_level_off", feature = "release_max_level_trace"),
387 all(feature = "release_max_level_error", feature = "release_max_level_warn"),
388 all(feature = "release_max_level_error", feature = "release_max_level_info"),
389 all(feature = "release_max_level_error", feature = "release_max_level_debug"),
390 all(feature = "release_max_level_error", feature = "release_max_level_trace"),
391 all(feature = "release_max_level_warn", feature = "release_max_level_info"),
392 all(feature = "release_max_level_warn", feature = "release_max_level_debug"),
393 all(feature = "release_max_level_warn", feature = "release_max_level_trace"),
394 all(feature = "release_max_level_info", feature = "release_max_level_debug"),
395 all(feature = "release_max_level_info", feature = "release_max_level_trace"),
396 all(feature = "release_max_level_debug", feature = "release_max_level_trace"),
397))]
398compile_error!("multiple release_max_level_* features set");
399
400#[cfg(feature = "alloc")]
401extern crate alloc;
402#[cfg(all(not(feature = "std"), not(test)))]
403extern crate core as std;
404
405#[cfg(feature = "alloc")]
406use alloc::boxed::Box;
407use std::cfg;
408#[cfg(feature = "std")]
409use std::error;
410use std::str::FromStr;
411use std::{cmp, fmt, mem};
412
413#[macro_use]
414mod macros;
415mod serde;
416
417#[cfg(feature = "kv")]
418pub mod kv;
419
420#[cfg(target_has_atomic = "ptr")]
421use std::sync::atomic::{AtomicUsize, Ordering};
422
423#[cfg(not(target_has_atomic = "ptr"))]
424use std::cell::Cell;
425#[cfg(not(target_has_atomic = "ptr"))]
426use std::sync::atomic::Ordering;
427
428#[cfg(not(target_has_atomic = "ptr"))]
429struct AtomicUsize {
430 v: Cell<usize>,
431}
432
433#[cfg(not(target_has_atomic = "ptr"))]
434impl AtomicUsize {
435 const fn new(v: usize) -> AtomicUsize {
436 AtomicUsize { v: Cell::new(v) }
437 }
438
439 fn load(&self, _order: Ordering) -> usize {
440 self.v.get()
441 }
442
443 fn store(&self, val: usize, _order: Ordering) {
444 self.v.set(val)
445 }
446}
447
448#[cfg(not(target_has_atomic = "ptr"))]
451unsafe impl Sync for AtomicUsize {}
452
453static mut LOGGER: &dyn Log = &NopLogger;
456
457static STATE: AtomicUsize = AtomicUsize::new(0);
458
459const UNINITIALIZED: usize = 0;
463const INITIALIZING: usize = 1;
464const INITIALIZED: usize = 2;
465
466static MAX_LOG_LEVEL_FILTER: AtomicUsize = AtomicUsize::new(0);
467
468static LOG_LEVEL_NAMES: [&str; 6] = ["OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"];
469
470static SET_LOGGER_ERROR: &str = "attempted to set a logger after the logging system \
471 was already initialized";
472static LEVEL_PARSE_ERROR: &str =
473 "attempted to convert a string that doesn't match an existing log level";
474
475#[repr(usize)]
482#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for Level {
}
#[automatically_derived]impl ::core::clone::Clone for Level {
#[inline]
#[rustc_trivial_field_reads]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::Copy for Level { }Copy, #[automatically_derived]impl ::core::marker::StructuralPartialEq for Level { }
#[automatically_derived]impl ::core::cmp::PartialEq for Level {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for Level { }Eq, #[automatically_derived]impl ::core::cmp::PartialOrd for Level {
#[inline]
fn partial_cmp(&self, other: &Self)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]impl ::core::cmp::Ord for Level {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self),
&::core::intrinsics::discriminant_value(other))
}
}Ord, #[automatically_derived]impl ::core::fmt::Debug for Level {
#[inline]
#[rustc_trivial_field_reads]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_c_like_enum_write_str(f,
"Error Warn Info Debug Trace",
match self {
Level::Error => 0usize,
Level::Warn => 6usize,
Level::Info => 11usize,
Level::Debug => 16usize,
Level::Trace => 22usize,
})
}
}Debug, #[automatically_derived]impl ::core::hash::Hash for Level {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
state)
}
}Hash)]
483pub enum Level {
484 Error = 1,
491 Warn,
495 Info,
499 Debug,
503 Trace,
507}
508
509impl PartialEq<LevelFilter> for Level {
510 #[inline]
511 fn eq(&self, other: &LevelFilter) -> bool {
512 *self as usize == *other as usize
513 }
514}
515
516impl PartialOrd<LevelFilter> for Level {
517 #[inline]
518 fn partial_cmp(&self, other: &LevelFilter) -> Option<cmp::Ordering> {
519 Some((*self as usize).cmp(&(*other as usize)))
520 }
521}
522
523impl FromStr for Level {
524 type Err = ParseLevelError;
525 fn from_str(level: &str) -> Result<Level, Self::Err> {
526 for idx in 1..LOG_LEVEL_NAMES.len() {
528 if LOG_LEVEL_NAMES[idx].eq_ignore_ascii_case(level) {
529 return Ok(Level::from_usize(idx).unwrap());
530 }
531 }
532 Err(ParseLevelError(()))
533 }
534}
535
536impl fmt::Display for Level {
537 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
538 fmt.pad(self.as_str())
539 }
540}
541
542impl Level {
543 fn from_usize(u: usize) -> Option<Level> {
544 match u {
545 1 => Some(Level::Error),
546 2 => Some(Level::Warn),
547 3 => Some(Level::Info),
548 4 => Some(Level::Debug),
549 5 => Some(Level::Trace),
550 _ => None,
551 }
552 }
553
554 #[inline]
556 pub fn max() -> Level {
557 Level::Trace
558 }
559
560 #[inline]
562 pub fn to_level_filter(&self) -> LevelFilter {
563 LevelFilter::from_usize(*self as usize).unwrap()
564 }
565
566 pub fn as_str(&self) -> &'static str {
570 LOG_LEVEL_NAMES[*self as usize]
571 }
572
573 pub fn iter() -> impl Iterator<Item = Self> {
588 (1..6).map(|i| Self::from_usize(i).unwrap())
589 }
590
591 pub fn increment_severity(&self) -> Self {
608 let current = *self as usize;
609 Self::from_usize(current + 1).unwrap_or(*self)
610 }
611
612 pub fn decrement_severity(&self) -> Self {
629 let current = *self as usize;
630 Self::from_usize(current.saturating_sub(1)).unwrap_or(*self)
631 }
632}
633
634#[repr(usize)]
643#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for LevelFilter {
}
#[automatically_derived]impl ::core::clone::Clone for LevelFilter {
#[inline]
#[rustc_trivial_field_reads]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::Copy for LevelFilter { }Copy, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
LevelFilter {
}
#[automatically_derived]impl ::core::cmp::PartialEq for LevelFilter {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for LevelFilter { }Eq, #[automatically_derived]impl ::core::cmp::PartialOrd for LevelFilter {
#[inline]
fn partial_cmp(&self, other: &Self)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]impl ::core::cmp::Ord for LevelFilter {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self),
&::core::intrinsics::discriminant_value(other))
}
}Ord, #[automatically_derived]impl ::core::fmt::Debug for LevelFilter {
#[inline]
#[rustc_trivial_field_reads]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_c_like_enum_write_str(f,
"Off Error Warn Info Debug Trace",
match self {
LevelFilter::Off => 0usize,
LevelFilter::Error => 4usize,
LevelFilter::Warn => 10usize,
LevelFilter::Info => 15usize,
LevelFilter::Debug => 20usize,
LevelFilter::Trace => 26usize,
})
}
}Debug, #[automatically_derived]impl ::core::hash::Hash for LevelFilter {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
state)
}
}Hash)]
644pub enum LevelFilter {
645 Off,
647 Error,
649 Warn,
651 Info,
653 Debug,
655 Trace,
657}
658
659impl PartialEq<Level> for LevelFilter {
660 #[inline]
661 fn eq(&self, other: &Level) -> bool {
662 other.eq(self)
663 }
664}
665
666impl PartialOrd<Level> for LevelFilter {
667 #[inline]
668 fn partial_cmp(&self, other: &Level) -> Option<cmp::Ordering> {
669 Some((*self as usize).cmp(&(*other as usize)))
670 }
671}
672
673impl FromStr for LevelFilter {
674 type Err = ParseLevelError;
675 fn from_str(level: &str) -> Result<LevelFilter, Self::Err> {
676 for idx in 0..LOG_LEVEL_NAMES.len() {
678 if LOG_LEVEL_NAMES[idx].eq_ignore_ascii_case(level) {
679 return Ok(LevelFilter::from_usize(idx).unwrap());
680 }
681 }
682 Err(ParseLevelError(()))
683 }
684}
685
686impl fmt::Display for LevelFilter {
687 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
688 fmt.pad(self.as_str())
689 }
690}
691
692impl LevelFilter {
693 fn from_usize(u: usize) -> Option<LevelFilter> {
694 match u {
695 0 => Some(LevelFilter::Off),
696 1 => Some(LevelFilter::Error),
697 2 => Some(LevelFilter::Warn),
698 3 => Some(LevelFilter::Info),
699 4 => Some(LevelFilter::Debug),
700 5 => Some(LevelFilter::Trace),
701 _ => None,
702 }
703 }
704
705 #[inline]
707 pub fn max() -> LevelFilter {
708 LevelFilter::Trace
709 }
710
711 #[inline]
715 pub fn to_level(&self) -> Option<Level> {
716 Level::from_usize(*self as usize)
717 }
718
719 pub fn as_str(&self) -> &'static str {
723 LOG_LEVEL_NAMES[*self as usize]
724 }
725
726 pub fn iter() -> impl Iterator<Item = Self> {
741 (0..6).map(|i| Self::from_usize(i).unwrap())
742 }
743
744 pub fn increment_severity(&self) -> Self {
761 let current = *self as usize;
762 Self::from_usize(current + 1).unwrap_or(*self)
763 }
764
765 pub fn decrement_severity(&self) -> Self {
783 let current = *self as usize;
784 Self::from_usize(current.saturating_sub(1)).unwrap_or(*self)
785 }
786}
787
788#[derive(#[automatically_derived]impl<'a> ::core::marker::Copy for MaybeStaticStr<'a> {
}Copy, #[automatically_derived]#[doc(hidden)]unsafe impl<'a>
::core::clone::TrivialClone for MaybeStaticStr<'a> {
}
#[automatically_derived]impl<'a> ::core::clone::Clone for MaybeStaticStr<'a> {
#[inline]
#[rustc_trivial_field_reads]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<&'static str>;
let _: ::core::clone::AssertParamIsClone<&'a str>;
*self
}
}Clone, #[automatically_derived]impl<'a> ::core::fmt::Debug for MaybeStaticStr<'a> {
#[inline]
#[rustc_trivial_field_reads]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Static(__self_0) =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"Static", &__self_0),
Self::Borrowed(__self_0) =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"Borrowed", &__self_0),
}
}
}Debug)]
789enum MaybeStaticStr<'a> {
790 Static(&'static str),
791 Borrowed(&'a str),
792}
793
794impl<'a> MaybeStaticStr<'a> {
795 #[inline]
796 fn get(&self) -> &'a str {
797 match *self {
798 MaybeStaticStr::Static(s) => s,
799 MaybeStaticStr::Borrowed(s) => s,
800 }
801 }
802}
803
804impl Eq for MaybeStaticStr<'_> {}
805
806impl PartialEq for MaybeStaticStr<'_> {
807 fn eq(&self, other: &Self) -> bool {
808 self.get() == other.get()
809 }
810}
811
812impl Ord for MaybeStaticStr<'_> {
813 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
814 self.get().cmp(other.get())
815 }
816}
817
818impl PartialOrd for MaybeStaticStr<'_> {
819 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
820 Some(self.cmp(other))
821 }
822}
823
824impl std::hash::Hash for MaybeStaticStr<'_> {
825 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
826 self.get().hash(state);
827 }
828}
829
830#[derive(#[automatically_derived]impl<'a> ::core::clone::Clone for Record<'a> {
#[inline]
#[rustc_trivial_field_reads]
fn clone(&self) -> Self {
Record {
metadata: ::core::clone::Clone::clone(&self.metadata),
args: ::core::clone::Clone::clone(&self.args),
module_path: ::core::clone::Clone::clone(&self.module_path),
file: ::core::clone::Clone::clone(&self.file),
line: ::core::clone::Clone::clone(&self.line),
}
}
}Clone, #[automatically_derived]impl<'a> ::core::fmt::Debug for Record<'a> {
#[inline]
#[rustc_trivial_field_reads]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field5_finish(f,
"Record metadata args module_path file line", &self.metadata,
&self.args, &self.module_path, &self.file, &&self.line)
}
}Debug)]
876pub struct Record<'a> {
877 metadata: Metadata<'a>,
878 args: fmt::Arguments<'a>,
879 module_path: Option<MaybeStaticStr<'a>>,
880 file: Option<MaybeStaticStr<'a>>,
881 line: Option<u32>,
882 #[cfg(feature = "kv")]
883 key_values: KeyValues<'a>,
884}
885
886#[cfg(feature = "kv")]
891#[derive(Clone)]
892struct KeyValues<'a>(&'a dyn kv::Source);
893
894#[cfg(feature = "kv")]
895impl<'a> fmt::Debug for KeyValues<'a> {
896 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
897 let mut visitor = f.debug_map();
898 self.0.visit(&mut visitor).map_err(|_| fmt::Error)?;
899 visitor.finish()
900 }
901}
902
903impl<'a> Record<'a> {
904 #[inline]
906 pub fn builder() -> RecordBuilder<'a> {
907 RecordBuilder::new()
908 }
909
910 #[inline]
912 pub fn args(&self) -> &fmt::Arguments<'a> {
913 &self.args
914 }
915
916 #[inline]
918 pub fn metadata(&self) -> &Metadata<'a> {
919 &self.metadata
920 }
921
922 #[inline]
924 pub fn level(&self) -> Level {
925 self.metadata.level()
926 }
927
928 #[inline]
930 pub fn target(&self) -> &'a str {
931 self.metadata.target()
932 }
933
934 #[inline]
936 pub fn module_path(&self) -> Option<&'a str> {
937 self.module_path.map(|s| s.get())
938 }
939
940 #[inline]
942 pub fn module_path_static(&self) -> Option<&'static str> {
943 match self.module_path {
944 Some(MaybeStaticStr::Static(s)) => Some(s),
945 _ => None,
946 }
947 }
948
949 #[inline]
951 pub fn file(&self) -> Option<&'a str> {
952 self.file.map(|s| s.get())
953 }
954
955 #[inline]
957 pub fn file_static(&self) -> Option<&'static str> {
958 match self.file {
959 Some(MaybeStaticStr::Static(s)) => Some(s),
960 _ => None,
961 }
962 }
963
964 #[inline]
966 pub fn line(&self) -> Option<u32> {
967 self.line
968 }
969
970 #[cfg(feature = "kv")]
972 #[inline]
973 pub fn key_values(&self) -> &dyn kv::Source {
974 self.key_values.0
975 }
976
977 #[cfg(feature = "kv")]
979 #[inline]
980 pub fn to_builder(&self) -> RecordBuilder<'_> {
981 RecordBuilder {
982 record: Record {
983 metadata: Metadata {
984 level: self.metadata.level,
985 target: self.metadata.target,
986 },
987 args: self.args,
988 module_path: self.module_path,
989 file: self.file,
990 line: self.line,
991 key_values: self.key_values.clone(),
992 },
993 }
994 }
995}
996
997#[derive(#[automatically_derived]impl<'a> ::core::fmt::Debug for RecordBuilder<'a> {
#[inline]
#[rustc_trivial_field_reads]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"RecordBuilder record", &&self.record)
}
}Debug)]
1037pub struct RecordBuilder<'a> {
1038 record: Record<'a>,
1039}
1040
1041impl<'a> RecordBuilder<'a> {
1042 #[inline]
1055 pub fn new() -> RecordBuilder<'a> {
1056 RecordBuilder {
1057 record: Record {
1058 args: format_args!("")format_args!(""),
1059 metadata: Metadata::builder().build(),
1060 module_path: None,
1061 file: None,
1062 line: None,
1063 #[cfg(feature = "kv")]
1064 key_values: KeyValues(&None::<(kv::Key, kv::Value)>),
1065 },
1066 }
1067 }
1068
1069 #[inline]
1071 pub fn args(&mut self, args: fmt::Arguments<'a>) -> &mut RecordBuilder<'a> {
1072 self.record.args = args;
1073 self
1074 }
1075
1076 #[inline]
1078 pub fn metadata(&mut self, metadata: Metadata<'a>) -> &mut RecordBuilder<'a> {
1079 self.record.metadata = metadata;
1080 self
1081 }
1082
1083 #[inline]
1085 pub fn level(&mut self, level: Level) -> &mut RecordBuilder<'a> {
1086 self.record.metadata.level = level;
1087 self
1088 }
1089
1090 #[inline]
1092 pub fn target(&mut self, target: &'a str) -> &mut RecordBuilder<'a> {
1093 self.record.metadata.target = target;
1094 self
1095 }
1096
1097 #[inline]
1099 pub fn module_path(&mut self, path: Option<&'a str>) -> &mut RecordBuilder<'a> {
1100 self.record.module_path = path.map(MaybeStaticStr::Borrowed);
1101 self
1102 }
1103
1104 #[inline]
1106 pub fn module_path_static(&mut self, path: Option<&'static str>) -> &mut RecordBuilder<'a> {
1107 self.record.module_path = path.map(MaybeStaticStr::Static);
1108 self
1109 }
1110
1111 #[inline]
1113 pub fn file(&mut self, file: Option<&'a str>) -> &mut RecordBuilder<'a> {
1114 self.record.file = file.map(MaybeStaticStr::Borrowed);
1115 self
1116 }
1117
1118 #[inline]
1120 pub fn file_static(&mut self, file: Option<&'static str>) -> &mut RecordBuilder<'a> {
1121 self.record.file = file.map(MaybeStaticStr::Static);
1122 self
1123 }
1124
1125 #[inline]
1127 pub fn line(&mut self, line: Option<u32>) -> &mut RecordBuilder<'a> {
1128 self.record.line = line;
1129 self
1130 }
1131
1132 #[cfg(feature = "kv")]
1134 #[inline]
1135 pub fn key_values(&mut self, kvs: &'a dyn kv::Source) -> &mut RecordBuilder<'a> {
1136 self.record.key_values = KeyValues(kvs);
1137 self
1138 }
1139
1140 #[inline]
1142 pub fn build(&self) -> Record<'a> {
1143 self.record.clone()
1144 }
1145}
1146
1147impl Default for RecordBuilder<'_> {
1148 fn default() -> Self {
1149 Self::new()
1150 }
1151}
1152
1153#[derive(#[automatically_derived]impl<'a> ::core::clone::Clone for Metadata<'a> {
#[inline]
#[rustc_trivial_field_reads]
fn clone(&self) -> Self {
Metadata {
level: ::core::clone::Clone::clone(&self.level),
target: ::core::clone::Clone::clone(&self.target),
}
}
}Clone, #[automatically_derived]impl<'a> ::core::cmp::Eq for Metadata<'a> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Level>;
let _: ::core::cmp::AssertParamIsEq<&'a str>;
}
}Eq, #[automatically_derived]impl<'a> ::core::marker::StructuralPartialEq for
Metadata<'a> {
}
#[automatically_derived]impl<'a> ::core::cmp::PartialEq for Metadata<'a> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.level == other.level && self.target == other.target
}
}PartialEq, #[automatically_derived]impl<'a> ::core::cmp::Ord for Metadata<'a> {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.level, &other.level) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.target, &other.target),
cmp => cmp,
}
}
}Ord, #[automatically_derived]impl<'a> ::core::cmp::PartialOrd for Metadata<'a> {
#[inline]
fn partial_cmp(&self, other: &Self)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]impl<'a> ::core::hash::Hash for Metadata<'a> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.level, state);
::core::hash::Hash::hash(&self.target, state)
}
}Hash, #[automatically_derived]impl<'a> ::core::fmt::Debug for Metadata<'a> {
#[inline]
#[rustc_trivial_field_reads]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Metadata level target", &self.level, &&self.target)
}
}Debug)]
1192pub struct Metadata<'a> {
1193 level: Level,
1194 target: &'a str,
1195}
1196
1197impl<'a> Metadata<'a> {
1198 #[inline]
1200 pub fn builder() -> MetadataBuilder<'a> {
1201 MetadataBuilder::new()
1202 }
1203
1204 #[inline]
1206 pub fn level(&self) -> Level {
1207 self.level
1208 }
1209
1210 #[inline]
1212 pub fn target(&self) -> &'a str {
1213 self.target
1214 }
1215}
1216
1217#[derive(#[automatically_derived]impl<'a> ::core::cmp::Eq for MetadataBuilder<'a> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Metadata<'a>>;
}
}Eq, #[automatically_derived]impl<'a> ::core::marker::StructuralPartialEq for
MetadataBuilder<'a> {
}
#[automatically_derived]impl<'a> ::core::cmp::PartialEq for
MetadataBuilder<'a> {
#[inline]
fn eq(&self, other: &Self) -> bool { self.metadata == other.metadata }
}PartialEq, #[automatically_derived]impl<'a> ::core::cmp::Ord for MetadataBuilder<'a> {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.metadata, &other.metadata)
}
}Ord, #[automatically_derived]impl<'a> ::core::cmp::PartialOrd for
MetadataBuilder<'a> {
#[inline]
fn partial_cmp(&self, other: &Self)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]impl<'a> ::core::hash::Hash for MetadataBuilder<'a> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.metadata, state)
}
}Hash, #[automatically_derived]impl<'a> ::core::fmt::Debug for MetadataBuilder<'a> {
#[inline]
#[rustc_trivial_field_reads]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"MetadataBuilder metadata", &&self.metadata)
}
}Debug)]
1234pub struct MetadataBuilder<'a> {
1235 metadata: Metadata<'a>,
1236}
1237
1238impl<'a> MetadataBuilder<'a> {
1239 #[inline]
1246 pub fn new() -> MetadataBuilder<'a> {
1247 MetadataBuilder {
1248 metadata: Metadata {
1249 level: Level::Info,
1250 target: "",
1251 },
1252 }
1253 }
1254
1255 #[inline]
1257 pub fn level(&mut self, arg: Level) -> &mut MetadataBuilder<'a> {
1258 self.metadata.level = arg;
1259 self
1260 }
1261
1262 #[inline]
1264 pub fn target(&mut self, target: &'a str) -> &mut MetadataBuilder<'a> {
1265 self.metadata.target = target;
1266 self
1267 }
1268
1269 #[inline]
1271 pub fn build(&self) -> Metadata<'a> {
1272 self.metadata.clone()
1273 }
1274}
1275
1276impl Default for MetadataBuilder<'_> {
1277 fn default() -> Self {
1278 Self::new()
1279 }
1280}
1281
1282pub trait Log: Sync + Send {
1284 fn enabled(&self, metadata: &Metadata) -> bool;
1297
1298 fn log(&self, record: &Record);
1306
1307 fn flush(&self);
1314}
1315
1316struct NopLogger;
1318
1319impl Log for NopLogger {
1320 fn enabled(&self, _: &Metadata) -> bool {
1321 false
1322 }
1323
1324 fn log(&self, _: &Record) {}
1325 fn flush(&self) {}
1326}
1327
1328impl<T> Log for &'_ T
1329where
1330 T: ?Sized + Log,
1331{
1332 fn enabled(&self, metadata: &Metadata) -> bool {
1333 (**self).enabled(metadata)
1334 }
1335
1336 fn log(&self, record: &Record) {
1337 (**self).log(record);
1338 }
1339 fn flush(&self) {
1340 (**self).flush();
1341 }
1342}
1343
1344#[cfg(feature = "alloc")]
1345impl<T> Log for Box<T>
1346where
1347 T: ?Sized + Log,
1348{
1349 fn enabled(&self, metadata: &Metadata) -> bool {
1350 self.as_ref().enabled(metadata)
1351 }
1352
1353 fn log(&self, record: &Record) {
1354 self.as_ref().log(record);
1355 }
1356 fn flush(&self) {
1357 self.as_ref().flush();
1358 }
1359}
1360
1361#[cfg(feature = "std")]
1362impl<T> Log for std::sync::Arc<T>
1363where
1364 T: ?Sized + Log,
1365{
1366 fn enabled(&self, metadata: &Metadata) -> bool {
1367 self.as_ref().enabled(metadata)
1368 }
1369
1370 fn log(&self, record: &Record) {
1371 self.as_ref().log(record);
1372 }
1373 fn flush(&self) {
1374 self.as_ref().flush();
1375 }
1376}
1377
1378#[inline]
1384#[cfg(target_has_atomic = "ptr")]
1385pub fn set_max_level(level: LevelFilter) {
1386 MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed);
1387}
1388
1389#[inline]
1409pub unsafe fn set_max_level_racy(level: LevelFilter) {
1410 MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed);
1414}
1415
1416#[inline(always)]
1430pub fn max_level() -> LevelFilter {
1431 unsafe { mem::transmute(MAX_LOG_LEVEL_FILTER.load(Ordering::Relaxed)) }
1438}
1439
1440#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))]
1454pub fn set_boxed_logger(logger: Box<dyn Log>) -> Result<(), SetLoggerError> {
1455 set_logger_inner(|| Box::leak(logger))
1456}
1457
1458#[cfg(target_has_atomic = "ptr")]
1512pub fn set_logger(logger: &'static dyn Log) -> Result<(), SetLoggerError> {
1513 set_logger_inner(|| logger)
1514}
1515
1516#[cfg(target_has_atomic = "ptr")]
1517fn set_logger_inner<F>(make_logger: F) -> Result<(), SetLoggerError>
1518where
1519 F: FnOnce() -> &'static dyn Log,
1520{
1521 match STATE.compare_exchange(
1522 UNINITIALIZED,
1523 INITIALIZING,
1524 Ordering::Acquire,
1525 Ordering::Relaxed,
1526 ) {
1527 Ok(UNINITIALIZED) => {
1528 unsafe {
1529 LOGGER = make_logger();
1530 }
1531 STATE.store(INITIALIZED, Ordering::Release);
1532 Ok(())
1533 }
1534 Err(INITIALIZING) => {
1535 while STATE.load(Ordering::Relaxed) == INITIALIZING {
1536 std::hint::spin_loop();
1537 }
1538 Err(SetLoggerError(()))
1539 }
1540 _ => Err(SetLoggerError(())),
1541 }
1542}
1543
1544pub unsafe fn set_logger_racy(logger: &'static dyn Log) -> Result<(), SetLoggerError> {
1564 match STATE.load(Ordering::Acquire) {
1565 UNINITIALIZED => {
1566 LOGGER = logger;
1567 STATE.store(INITIALIZED, Ordering::Release);
1568 Ok(())
1569 }
1570 INITIALIZING => {
1571 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("set_logger_racy must not be used with other initialization functions")));
}unreachable!("set_logger_racy must not be used with other initialization functions")
1573 }
1574 _ => Err(SetLoggerError(())),
1575 }
1576}
1577
1578#[allow(missing_copy_implementations)]
1582#[derive(#[automatically_derived]#[allow(missing_copy_implementations)]
impl ::core::fmt::Debug for SetLoggerError {
#[inline]
#[rustc_trivial_field_reads]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"SetLoggerError", &&self.0)
}
}Debug)]
1583pub struct SetLoggerError(());
1584
1585impl fmt::Display for SetLoggerError {
1586 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1587 fmt.write_str(SET_LOGGER_ERROR)
1588 }
1589}
1590
1591#[cfg(feature = "std")]
1593impl error::Error for SetLoggerError {}
1594
1595#[allow(missing_copy_implementations)]
1599#[derive(#[automatically_derived]#[allow(missing_copy_implementations)]
impl ::core::fmt::Debug for ParseLevelError {
#[inline]
#[rustc_trivial_field_reads]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"ParseLevelError", &&self.0)
}
}Debug, #[automatically_derived]#[allow(missing_copy_implementations)]
impl ::core::marker::StructuralPartialEq for ParseLevelError { }
#[automatically_derived]#[allow(missing_copy_implementations)]
impl ::core::cmp::PartialEq for ParseLevelError {
#[inline]
fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]#[allow(missing_copy_implementations)]
impl ::core::cmp::Eq for ParseLevelError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<()>;
}
}Eq)]
1600pub struct ParseLevelError(());
1601
1602impl fmt::Display for ParseLevelError {
1603 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1604 fmt.write_str(LEVEL_PARSE_ERROR)
1605 }
1606}
1607
1608#[cfg(feature = "std")]
1610impl error::Error for ParseLevelError {}
1611
1612pub fn logger() -> &'static dyn Log {
1616 if STATE.load(Ordering::Acquire) != INITIALIZED {
1625 static NOP: NopLogger = NopLogger;
1626 &NOP
1627 } else {
1628 unsafe { LOGGER }
1629 }
1630}
1631
1632#[doc(hidden)]
1634pub mod __private_api;
1635
1636pub const STATIC_MAX_LEVEL: LevelFilter = match truecfg!(debug_assertions) {
1646 false if falsecfg!(feature = "release_max_level_off") => LevelFilter::Off,
1647 false if falsecfg!(feature = "release_max_level_error") => LevelFilter::Error,
1648 false if falsecfg!(feature = "release_max_level_warn") => LevelFilter::Warn,
1649 false if falsecfg!(feature = "release_max_level_info") => LevelFilter::Info,
1650 false if falsecfg!(feature = "release_max_level_debug") => LevelFilter::Debug,
1651 false if falsecfg!(feature = "release_max_level_trace") => LevelFilter::Trace,
1652 _ if falsecfg!(feature = "max_level_off") => LevelFilter::Off,
1653 _ if falsecfg!(feature = "max_level_error") => LevelFilter::Error,
1654 _ if falsecfg!(feature = "max_level_warn") => LevelFilter::Warn,
1655 _ if falsecfg!(feature = "max_level_info") => LevelFilter::Info,
1656 _ if falsecfg!(feature = "max_level_debug") => LevelFilter::Debug,
1657 _ => LevelFilter::Trace,
1658};
1659
1660#[cfg(test)]
1661mod tests {
1662 use super::{Level, LevelFilter, ParseLevelError, STATIC_MAX_LEVEL};
1663
1664 #[test]
1665 fn test_levelfilter_from_str() {
1666 let tests = [
1667 ("off", Ok(LevelFilter::Off)),
1668 ("error", Ok(LevelFilter::Error)),
1669 ("warn", Ok(LevelFilter::Warn)),
1670 ("info", Ok(LevelFilter::Info)),
1671 ("debug", Ok(LevelFilter::Debug)),
1672 ("trace", Ok(LevelFilter::Trace)),
1673 ("OFF", Ok(LevelFilter::Off)),
1674 ("ERROR", Ok(LevelFilter::Error)),
1675 ("WARN", Ok(LevelFilter::Warn)),
1676 ("INFO", Ok(LevelFilter::Info)),
1677 ("DEBUG", Ok(LevelFilter::Debug)),
1678 ("TRACE", Ok(LevelFilter::Trace)),
1679 ("asdf", Err(ParseLevelError(()))),
1680 ];
1681 for &(s, ref expected) in &tests {
1682 assert_eq!(expected, &s.parse());
1683 }
1684 }
1685
1686 #[test]
1687 fn test_level_from_str() {
1688 let tests = [
1689 ("OFF", Err(ParseLevelError(()))),
1690 ("error", Ok(Level::Error)),
1691 ("warn", Ok(Level::Warn)),
1692 ("info", Ok(Level::Info)),
1693 ("debug", Ok(Level::Debug)),
1694 ("trace", Ok(Level::Trace)),
1695 ("ERROR", Ok(Level::Error)),
1696 ("WARN", Ok(Level::Warn)),
1697 ("INFO", Ok(Level::Info)),
1698 ("DEBUG", Ok(Level::Debug)),
1699 ("TRACE", Ok(Level::Trace)),
1700 ("asdf", Err(ParseLevelError(()))),
1701 ];
1702 for &(s, ref expected) in &tests {
1703 assert_eq!(expected, &s.parse());
1704 }
1705 }
1706
1707 #[test]
1708 fn test_level_as_str() {
1709 let tests = &[
1710 (Level::Error, "ERROR"),
1711 (Level::Warn, "WARN"),
1712 (Level::Info, "INFO"),
1713 (Level::Debug, "DEBUG"),
1714 (Level::Trace, "TRACE"),
1715 ];
1716 for (input, expected) in tests {
1717 assert_eq!(*expected, input.as_str());
1718 }
1719 }
1720
1721 #[test]
1722 fn test_level_show() {
1723 assert_eq!("INFO", Level::Info.to_string());
1724 assert_eq!("ERROR", Level::Error.to_string());
1725 }
1726
1727 #[test]
1728 fn test_levelfilter_show() {
1729 assert_eq!("OFF", LevelFilter::Off.to_string());
1730 assert_eq!("ERROR", LevelFilter::Error.to_string());
1731 }
1732
1733 #[test]
1734 fn test_cross_cmp() {
1735 assert!(Level::Debug > LevelFilter::Error);
1736 assert!(LevelFilter::Warn < Level::Trace);
1737 assert!(LevelFilter::Off < Level::Error);
1738 }
1739
1740 #[test]
1741 fn test_cross_eq() {
1742 assert!(Level::Error == LevelFilter::Error);
1743 assert!(LevelFilter::Off != Level::Error);
1744 assert!(Level::Trace == LevelFilter::Trace);
1745 }
1746
1747 #[test]
1748 fn test_to_level() {
1749 assert_eq!(Some(Level::Error), LevelFilter::Error.to_level());
1750 assert_eq!(None, LevelFilter::Off.to_level());
1751 assert_eq!(Some(Level::Debug), LevelFilter::Debug.to_level());
1752 }
1753
1754 #[test]
1755 fn test_to_level_filter() {
1756 assert_eq!(LevelFilter::Error, Level::Error.to_level_filter());
1757 assert_eq!(LevelFilter::Trace, Level::Trace.to_level_filter());
1758 }
1759
1760 #[test]
1761 fn test_level_filter_as_str() {
1762 let tests = &[
1763 (LevelFilter::Off, "OFF"),
1764 (LevelFilter::Error, "ERROR"),
1765 (LevelFilter::Warn, "WARN"),
1766 (LevelFilter::Info, "INFO"),
1767 (LevelFilter::Debug, "DEBUG"),
1768 (LevelFilter::Trace, "TRACE"),
1769 ];
1770 for (input, expected) in tests {
1771 assert_eq!(*expected, input.as_str());
1772 }
1773 }
1774
1775 #[test]
1776 fn test_level_up() {
1777 let info = Level::Info;
1778 let up = info.increment_severity();
1779 assert_eq!(up, Level::Debug);
1780
1781 let trace = Level::Trace;
1782 let up = trace.increment_severity();
1783 assert_eq!(up, trace);
1785 }
1786
1787 #[test]
1788 fn test_level_filter_up() {
1789 let info = LevelFilter::Info;
1790 let up = info.increment_severity();
1791 assert_eq!(up, LevelFilter::Debug);
1792
1793 let trace = LevelFilter::Trace;
1794 let up = trace.increment_severity();
1795 assert_eq!(up, trace);
1797 }
1798
1799 #[test]
1800 fn test_level_down() {
1801 let info = Level::Info;
1802 let down = info.decrement_severity();
1803 assert_eq!(down, Level::Warn);
1804
1805 let error = Level::Error;
1806 let down = error.decrement_severity();
1807 assert_eq!(down, error);
1809 }
1810
1811 #[test]
1812 fn test_level_filter_down() {
1813 let info = LevelFilter::Info;
1814 let down = info.decrement_severity();
1815 assert_eq!(down, LevelFilter::Warn);
1816
1817 let error = LevelFilter::Error;
1818 let down = error.decrement_severity();
1819 assert_eq!(down, LevelFilter::Off);
1820 assert_eq!(down.decrement_severity(), down);
1822 }
1823
1824 #[test]
1825 #[cfg_attr(not(debug_assertions), ignore)]
1826 fn test_static_max_level_debug() {
1827 if cfg!(feature = "max_level_off") {
1828 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Off);
1829 } else if cfg!(feature = "max_level_error") {
1830 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Error);
1831 } else if cfg!(feature = "max_level_warn") {
1832 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Warn);
1833 } else if cfg!(feature = "max_level_info") {
1834 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Info);
1835 } else if cfg!(feature = "max_level_debug") {
1836 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Debug);
1837 } else {
1838 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Trace);
1839 }
1840 }
1841
1842 #[test]
1843 #[cfg_attr(debug_assertions, ignore)]
1844 fn test_static_max_level_release() {
1845 if cfg!(feature = "release_max_level_off") {
1846 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Off);
1847 } else if cfg!(feature = "release_max_level_error") {
1848 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Error);
1849 } else if cfg!(feature = "release_max_level_warn") {
1850 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Warn);
1851 } else if cfg!(feature = "release_max_level_info") {
1852 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Info);
1853 } else if cfg!(feature = "release_max_level_debug") {
1854 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Debug);
1855 } else if cfg!(feature = "release_max_level_trace") {
1856 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Trace);
1857 } else if cfg!(feature = "max_level_off") {
1858 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Off);
1859 } else if cfg!(feature = "max_level_error") {
1860 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Error);
1861 } else if cfg!(feature = "max_level_warn") {
1862 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Warn);
1863 } else if cfg!(feature = "max_level_info") {
1864 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Info);
1865 } else if cfg!(feature = "max_level_debug") {
1866 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Debug);
1867 } else {
1868 assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Trace);
1869 }
1870 }
1871
1872 #[test]
1873 #[cfg(feature = "std")]
1874 fn test_error_trait() {
1875 use super::SetLoggerError;
1876 let e = SetLoggerError(());
1877 assert_eq!(
1878 &e.to_string(),
1879 "attempted to set a logger after the logging system \
1880 was already initialized"
1881 );
1882 }
1883
1884 #[test]
1885 fn test_metadata_builder() {
1886 use super::MetadataBuilder;
1887 let target = "myApp";
1888 let metadata_test = MetadataBuilder::new()
1889 .level(Level::Debug)
1890 .target(target)
1891 .build();
1892 assert_eq!(metadata_test.level(), Level::Debug);
1893 assert_eq!(metadata_test.target(), "myApp");
1894 }
1895
1896 #[test]
1897 fn test_metadata_convenience_builder() {
1898 use super::Metadata;
1899 let target = "myApp";
1900 let metadata_test = Metadata::builder()
1901 .level(Level::Debug)
1902 .target(target)
1903 .build();
1904 assert_eq!(metadata_test.level(), Level::Debug);
1905 assert_eq!(metadata_test.target(), "myApp");
1906 }
1907
1908 #[test]
1909 fn test_record_builder() {
1910 use super::{MetadataBuilder, RecordBuilder};
1911 let target = "myApp";
1912 let metadata = MetadataBuilder::new().target(target).build();
1913 let fmt_args = format_args!("hello");
1914 let record_test = RecordBuilder::new()
1915 .args(fmt_args)
1916 .metadata(metadata)
1917 .module_path(Some("foo"))
1918 .file(Some("bar"))
1919 .line(Some(30))
1920 .build();
1921 assert_eq!(record_test.metadata().target(), "myApp");
1922 assert_eq!(record_test.module_path(), Some("foo"));
1923 assert_eq!(record_test.file(), Some("bar"));
1924 assert_eq!(record_test.line(), Some(30));
1925 }
1926
1927 #[test]
1928 fn test_record_convenience_builder() {
1929 use super::{Metadata, Record};
1930 let target = "myApp";
1931 let metadata = Metadata::builder().target(target).build();
1932 let fmt_args = format_args!("hello");
1933 let record_test = Record::builder()
1934 .args(fmt_args)
1935 .metadata(metadata)
1936 .module_path(Some("foo"))
1937 .file(Some("bar"))
1938 .line(Some(30))
1939 .build();
1940 assert_eq!(record_test.target(), "myApp");
1941 assert_eq!(record_test.module_path(), Some("foo"));
1942 assert_eq!(record_test.file(), Some("bar"));
1943 assert_eq!(record_test.line(), Some(30));
1944 }
1945
1946 #[test]
1947 fn test_record_complete_builder() {
1948 use super::{Level, Record};
1949 let target = "myApp";
1950 let record_test = Record::builder()
1951 .module_path(Some("foo"))
1952 .file(Some("bar"))
1953 .line(Some(30))
1954 .target(target)
1955 .level(Level::Error)
1956 .build();
1957 assert_eq!(record_test.target(), "myApp");
1958 assert_eq!(record_test.level(), Level::Error);
1959 assert_eq!(record_test.module_path(), Some("foo"));
1960 assert_eq!(record_test.file(), Some("bar"));
1961 assert_eq!(record_test.line(), Some(30));
1962 }
1963
1964 #[test]
1965 #[cfg(feature = "kv")]
1966 fn test_record_key_values_builder() {
1967 use super::Record;
1968 use crate::kv::{self, VisitSource};
1969
1970 struct TestVisitSource {
1971 seen_pairs: usize,
1972 }
1973
1974 impl<'kvs> VisitSource<'kvs> for TestVisitSource {
1975 fn visit_pair(
1976 &mut self,
1977 _: kv::Key<'kvs>,
1978 _: kv::Value<'kvs>,
1979 ) -> Result<(), kv::Error> {
1980 self.seen_pairs += 1;
1981 Ok(())
1982 }
1983 }
1984
1985 let kvs: &[(&str, i32)] = &[("a", 1), ("b", 2)];
1986 let record_test = Record::builder().key_values(&kvs).build();
1987
1988 let mut visitor = TestVisitSource { seen_pairs: 0 };
1989
1990 record_test.key_values().visit(&mut visitor).unwrap();
1991
1992 assert_eq!(2, visitor.seen_pairs);
1993 }
1994
1995 #[test]
1996 #[cfg(feature = "kv")]
1997 fn test_record_key_values_get_coerce() {
1998 use super::Record;
1999
2000 let kvs: &[(&str, &str)] = &[("a", "1"), ("b", "2")];
2001 let record = Record::builder().key_values(&kvs).build();
2002
2003 assert_eq!(
2004 "2",
2005 record
2006 .key_values()
2007 .get("b".into())
2008 .expect("missing key")
2009 .to_borrowed_str()
2010 .expect("invalid value")
2011 );
2012 }
2013
2014 #[test]
2017 fn test_foreign_impl() {
2018 use super::Log;
2019 #[cfg(feature = "std")]
2020 use std::sync::Arc;
2021
2022 fn assert_is_log<T: Log + ?Sized>() {}
2023
2024 assert_is_log::<&dyn Log>();
2025
2026 #[cfg(feature = "alloc")]
2027 assert_is_log::<Box<dyn Log>>();
2028
2029 #[cfg(feature = "std")]
2030 assert_is_log::<Arc<dyn Log>>();
2031
2032 #[allow(unused)]
2034 fn forall<T: Log + ?Sized>() {
2035 #[cfg(feature = "alloc")]
2036 assert_is_log::<Box<T>>();
2037
2038 assert_is_log::<&T>();
2039
2040 #[cfg(feature = "std")]
2041 assert_is_log::<Arc<T>>();
2042 }
2043 }
2044}