1use crate::InnerLevel;
2use core::fmt;
3use log::{Level, LevelFilter};
4pub use parser::*;
5use serde::de::DeserializeSeed;
6use serde::{de, Deserializer};
7
8pub(crate) mod parser {
9 use crate::{InnerLevel, TargetLevel};
10 use log::LevelFilter;
11 use std::str::FromStr;
12 use winnow::ascii::{alpha1, multispace0};
13 use winnow::combinator::{opt, repeat};
14 use winnow::token::take_while;
15 use winnow::{Parser, Result as WResult};
16
17 pub fn parse_level(input: &str) -> Result<InnerLevel, String> {
76 match (
77 level,
78 opt((multispace0, ',', repeat(1.., target_level)))
79 .map(|c| c.map(|(_, _, t)| t).unwrap_or_default()),
80 )
81 .parse(input)
82 {
83 Ok((level, targets)) => Ok((level, targets)),
84 Err(err) => Err(format!("Failed to parse level:\n{}", err)),
85 }
86 }
87
88 fn level(input: &mut &str) -> WResult<LevelFilter> {
89 alpha1.try_map(LevelFilter::from_str).parse_next(input)
90 }
91
92 fn target_level(input: &mut &str) -> WResult<TargetLevel> {
93 (multispace0, target_name, '=', level, multispace0, opt(','))
94 .map(|(_, name, _, level, _, _)| (name, level).into())
95 .parse_next(input)
96 }
97
98 fn target_name<'a>(input: &mut &'a str) -> WResult<&'a str> {
99 take_while(1.., ('0'..='9', 'A'..='Z', 'a'..='z', ':', '_')).parse_next(input)
100 }
101}
102
103#[allow(clippy::wrong_self_convention)]
104pub trait LevelInto {
105 fn into_level(&self) -> &str;
106}
107
108impl LevelInto for &str {
109 fn into_level(&self) -> &str {
110 self
111 }
112}
113
114impl LevelInto for String {
115 fn into_level(&self) -> &str {
116 self.as_str()
117 }
118}
119
120impl LevelInto for &String {
121 fn into_level(&self) -> &str {
122 self.as_str()
123 }
124}
125
126impl LevelInto for LevelFilter {
127 fn into_level(&self) -> &str {
128 self.as_str()
129 }
130}
131
132impl LevelInto for Level {
133 fn into_level(&self) -> &str {
134 self.as_str()
135 }
136}
137
138macro_rules! de_from {
139 ($err:expr) => {
140 LevelSerde::deserialize($err).map_err(de::Error::custom)
141 };
142}
143
144struct LevelSerde;
145
146impl LevelSerde {
147 fn deserialize<S>(s: S) -> Result<InnerLevel, String>
148 where
149 S: Into<String>,
150 {
151 let s = s.into();
152 parse_level(&s)
153 }
154}
155
156impl<'de> DeserializeSeed<'de> for LevelSerde {
157 type Value = InnerLevel;
158
159 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
160 where
161 D: Deserializer<'de>,
162 {
163 deserializer.deserialize_any(self)
164 }
165}
166
167impl serde::de::Visitor<'_> for LevelSerde {
168 type Value = InnerLevel;
169
170 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
171 formatter.write_str("inner level")
172 }
173
174 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
175 where
176 E: serde::de::Error,
177 {
178 de_from!(s)
179 }
180}
181
182pub fn deserialize_level<'de, D>(deserializer: D) -> Result<InnerLevel, D::Error>
183where
184 D: serde::Deserializer<'de>,
185{
186 deserializer.deserialize_any(LevelSerde)
187}
188
189#[cfg(test)]
190mod tests {
191 use super::*;
192
193 #[test]
194 fn quick_log_level1() {
195 fn quick_log_level<S: LevelInto>(level: S) {
196 level.into_level();
197 }
198
199 quick_log_level("debug");
200 quick_log_level("debug".to_string());
201 quick_log_level(LevelFilter::Debug);
202 quick_log_level(Level::Debug);
203 }
204}