1 //! WARNING: this is not part of the crate's public API and is subject to change at any time
2 
3 use self::sealed::KVs;
4 use crate::{Level, Metadata, Record};
5 use std::fmt::Arguments;
6 use std::panic::Location;
7 pub use std::{format_args, module_path, stringify};
8 
9 #[cfg(not(feature = "kv"))]
10 pub type Value<'a> = &'a str;
11 
12 mod sealed {
13     /// Types for the `kv` argument.
14     pub trait KVs<'a> {
into_kvs(self) -> Option<&'a [(&'a str, super::Value<'a>)]>15         fn into_kvs(self) -> Option<&'a [(&'a str, super::Value<'a>)]>;
16     }
17 }
18 
19 // Types for the `kv` argument.
20 
21 impl<'a> KVs<'a> for &'a [(&'a str, Value<'a>)] {
22     #[inline]
into_kvs(self) -> Option<&'a [(&'a str, Value<'a>)]>23     fn into_kvs(self) -> Option<&'a [(&'a str, Value<'a>)]> {
24         Some(self)
25     }
26 }
27 
28 impl<'a> KVs<'a> for () {
29     #[inline]
into_kvs(self) -> Option<&'a [(&'a str, Value<'a>)]>30     fn into_kvs(self) -> Option<&'a [(&'a str, Value<'a>)]> {
31         None
32     }
33 }
34 
35 // Log implementation.
36 
log_impl( args: Arguments, level: Level, &(target, module_path, loc): &(&str, &'static str, &'static Location), kvs: Option<&[(&str, Value)]>, )37 fn log_impl(
38     args: Arguments,
39     level: Level,
40     &(target, module_path, loc): &(&str, &'static str, &'static Location),
41     kvs: Option<&[(&str, Value)]>,
42 ) {
43     #[cfg(not(feature = "kv"))]
44     if kvs.is_some() {
45         panic!("key-value support is experimental and must be enabled using the `kv` feature")
46     }
47 
48     let mut builder = Record::builder();
49 
50     builder
51         .args(args)
52         .level(level)
53         .target(target)
54         .module_path_static(Some(module_path))
55         .file_static(Some(loc.file()))
56         .line(Some(loc.line()));
57 
58     #[cfg(feature = "kv")]
59     builder.key_values(&kvs);
60 
61     crate::logger().log(&builder.build());
62 }
63 
log<'a, K>( args: Arguments, level: Level, target_module_path_and_loc: &(&str, &'static str, &'static Location), kvs: K, ) where K: KVs<'a>,64 pub fn log<'a, K>(
65     args: Arguments,
66     level: Level,
67     target_module_path_and_loc: &(&str, &'static str, &'static Location),
68     kvs: K,
69 ) where
70     K: KVs<'a>,
71 {
72     log_impl(args, level, target_module_path_and_loc, kvs.into_kvs())
73 }
74 
enabled(level: Level, target: &str) -> bool75 pub fn enabled(level: Level, target: &str) -> bool {
76     crate::logger().enabled(&Metadata::builder().level(level).target(target).build())
77 }
78 
79 #[track_caller]
loc() -> &'static Location<'static>80 pub fn loc() -> &'static Location<'static> {
81     Location::caller()
82 }
83 
84 #[cfg(feature = "kv")]
85 mod kv_support {
86     use crate::kv;
87 
88     pub type Value<'a> = kv::Value<'a>;
89 
90     // NOTE: Many functions here accept a double reference &&V
91     // This is so V itself can be ?Sized, while still letting us
92     // erase it to some dyn Trait (because &T is sized)
93 
capture_to_value<'a, V: kv::ToValue + ?Sized>(v: &'a &'a V) -> Value<'a>94     pub fn capture_to_value<'a, V: kv::ToValue + ?Sized>(v: &'a &'a V) -> Value<'a> {
95         v.to_value()
96     }
97 
capture_debug<'a, V: core::fmt::Debug + ?Sized>(v: &'a &'a V) -> Value<'a>98     pub fn capture_debug<'a, V: core::fmt::Debug + ?Sized>(v: &'a &'a V) -> Value<'a> {
99         Value::from_debug(v)
100     }
101 
capture_display<'a, V: core::fmt::Display + ?Sized>(v: &'a &'a V) -> Value<'a>102     pub fn capture_display<'a, V: core::fmt::Display + ?Sized>(v: &'a &'a V) -> Value<'a> {
103         Value::from_display(v)
104     }
105 
106     #[cfg(feature = "kv_std")]
capture_error<'a>(v: &'a (dyn std::error::Error + 'static)) -> Value<'a>107     pub fn capture_error<'a>(v: &'a (dyn std::error::Error + 'static)) -> Value<'a> {
108         Value::from_dyn_error(v)
109     }
110 
111     #[cfg(feature = "kv_sval")]
capture_sval<'a, V: sval::Value + ?Sized>(v: &'a &'a V) -> Value<'a>112     pub fn capture_sval<'a, V: sval::Value + ?Sized>(v: &'a &'a V) -> Value<'a> {
113         Value::from_sval(v)
114     }
115 
116     #[cfg(feature = "kv_serde")]
capture_serde<'a, V: serde::Serialize + ?Sized>(v: &'a &'a V) -> Value<'a>117     pub fn capture_serde<'a, V: serde::Serialize + ?Sized>(v: &'a &'a V) -> Value<'a> {
118         Value::from_serde(v)
119     }
120 }
121 
122 #[cfg(feature = "kv")]
123 pub use self::kv_support::*;
124