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