Skip to content

Commit 364726a

Browse files
feat(filter): Add support for no_std environments
Co-authored-by: WolverinDEV <git@did.science>
1 parent 548e34a commit 364726a

File tree

8 files changed

+79
-34
lines changed

8 files changed

+79
-34
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ jobs:
7272
- uses: Swatinem/rust-cache@v2
7373
- uses: taiki-e/install-action@cargo-hack
7474
- name: Default features
75-
run: cargo hack check --each-feature --locked --rust-version --ignore-private --workspace --all-targets --keep-going
75+
run: |
76+
cargo hack check --each-feature --locked --rust-version --ignore-private --package env_logger --all-targets --keep-going
77+
cargo hack check --each-feature --locked --version-range 1.81..=1.81 --ignore-private --package env_filter --all-targets --keep-going
7678
minimal-versions:
7779
name: Minimal versions
7880
strategy:

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ unstable-kv = ["kv"]
135135

136136
[dependencies]
137137
log = { version = "0.4.29", features = ["std"] }
138-
env_filter = { version = "1.0.0", path = "crates/env_filter", default-features = false }
138+
env_filter = { version = "1.0.0", path = "crates/env_filter", default-features = false, features = ["std"] }
139139
jiff = { version = "0.2.22", default-features = false, features = ["std"], optional = true }
140140
anstream = { version = "1.0.0", default-features = false, features = ["wincon"], optional = true }
141141
anstyle = { version = "1.0.13", optional = true }

crates/env_filter/Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ keywords = ["logging", "log", "logger"]
99
repository.workspace = true
1010
license.workspace = true
1111
edition.workspace = true
12-
rust-version.workspace = true
1312
include.workspace = true
1413

1514
[package.metadata.docs.rs]
@@ -26,12 +25,13 @@ pre-release-replacements = [
2625
]
2726

2827
[features]
29-
default = ["regex"]
28+
default = ["std", "regex"]
3029
regex = ["dep:regex"]
30+
std = ["regex/std"]
3131

3232
[dependencies]
33-
log = { version = "0.4.29", features = ["std"] }
34-
regex = { version = "1.12.3", optional = true, default-features=false, features=["std", "perf"] }
33+
log = { version = "0.4.29", default-features = false }
34+
regex = { version = "1.12.3", optional = true, default-features=false, features=["perf"] }
3535

3636
[dev-dependencies]
3737
snapbox = "1.0"

crates/env_filter/src/directive.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use alloc::string::String;
2+
13
use log::Level;
24
use log::LevelFilter;
35

crates/env_filter/src/filter.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use std::env;
2-
use std::fmt;
3-
use std::mem;
1+
use alloc::{borrow::ToOwned, string::ToString, vec::Vec};
2+
use core::{fmt, mem};
43

54
use log::{LevelFilter, Metadata, Record};
65

@@ -48,10 +47,11 @@ impl Builder {
4847
}
4948

5049
/// Initializes the filter builder from an environment.
50+
#[cfg(feature = "std")]
5151
pub fn from_env(env: &str) -> Builder {
5252
let mut builder = Builder::new();
5353

54-
if let Ok(s) = env::var(env) {
54+
if let Ok(s) = std::env::var(env) {
5555
builder.parse(&s);
5656
}
5757

@@ -108,7 +108,10 @@ impl Builder {
108108
} = parse_spec(filters);
109109

110110
for error in errors {
111+
#[cfg(feature = "std")]
111112
eprintln!("warning: {error}, ignoring it");
113+
#[cfg(not(feature = "std"))]
114+
log::warn!("{error}, ignoring it");
112115
}
113116

114117
self.filter = filter;
@@ -258,8 +261,9 @@ impl fmt::Debug for Filter {
258261

259262
#[cfg(test)]
260263
mod tests {
264+
use alloc::{borrow::ToOwned, vec, vec::Vec};
265+
261266
use log::{Level, LevelFilter};
262-
use snapbox::{assert_data_eq, str};
263267

264268
use super::{enabled, Builder, Directive, Filter};
265269

@@ -486,10 +490,12 @@ mod tests {
486490

487491
#[test]
488492
fn try_parse_invalid_filter() {
493+
#[allow(unused_variables)]
489494
let error = Builder::new().try_parse("info,crate1=invalid").unwrap_err();
490-
assert_data_eq!(
495+
#[cfg(feature = "std")]
496+
snapbox::assert_data_eq!(
491497
error,
492-
str!["error parsing logger filter: invalid logging spec 'invalid'"]
498+
snapbox::str!["error parsing logger filter: invalid logging spec 'invalid'"]
493499
);
494500
}
495501

crates/env_filter/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,14 @@
3838
//! ```
3939
4040
#![cfg_attr(docsrs, feature(doc_cfg))]
41+
#![cfg_attr(not(feature = "std"), no_std)]
4142
#![warn(missing_docs)]
4243
#![warn(clippy::print_stderr)]
4344
#![warn(clippy::print_stdout)]
45+
#![warn(clippy::std_instead_of_core)]
46+
#![warn(clippy::std_instead_of_alloc)]
47+
48+
extern crate alloc;
4449

4550
mod directive;
4651
mod filter;

crates/env_filter/src/op.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use std::fmt;
1+
use alloc::string::{String, ToString};
2+
use core::fmt;
23

34
#[derive(Debug, Clone)]
45
pub(crate) struct FilterOp {

crates/env_filter/src/parser.rs

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
use alloc::{borrow::ToOwned, format, string::String, vec::Vec};
2+
use core::fmt::{Display, Formatter};
3+
14
use log::LevelFilter;
2-
use std::error::Error;
3-
use std::fmt::{Display, Formatter};
45

56
use crate::Directive;
67
use crate::FilterOp;
@@ -46,12 +47,17 @@ pub struct ParseError {
4647
}
4748

4849
impl Display for ParseError {
49-
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
50+
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
5051
write!(f, "error parsing logger filter: {}", self.details)
5152
}
5253
}
5354

54-
impl Error for ParseError {}
55+
#[cfg(feature = "std")]
56+
#[allow(clippy::std_instead_of_core)]
57+
impl std::error::Error for ParseError {}
58+
59+
#[cfg(not(feature = "std"))]
60+
impl core::error::Error for ParseError {}
5561

5662
/// Parse a logging specification string (e.g: `crate1,crate2::mod3,crate3::x=error/foo`)
5763
/// and return a vector with log directives.
@@ -115,9 +121,13 @@ pub(crate) fn parse_spec(spec: &str) -> ParseResult {
115121

116122
#[cfg(test)]
117123
mod tests {
124+
use alloc::{borrow::ToOwned, string::ToString};
125+
118126
use crate::ParseError;
119127
use log::LevelFilter;
120-
use snapbox::{assert_data_eq, str, Data, IntoData};
128+
#[cfg(feature = "std")]
129+
use snapbox::{assert_data_eq, str};
130+
use snapbox::{Data, IntoData};
121131

122132
use super::{parse_spec, ParseResult};
123133

@@ -164,6 +174,7 @@ mod tests {
164174
assert!(filter.is_none());
165175

166176
assert_eq!(errors.len(), 1);
177+
#[cfg(feature = "std")]
167178
assert_data_eq!(
168179
&errors[0],
169180
str!["invalid logging spec 'crate1::mod1=warn=info'"]
@@ -185,6 +196,7 @@ mod tests {
185196
assert!(filter.is_none());
186197

187198
assert_eq!(errors.len(), 1);
199+
#[cfg(feature = "std")]
188200
assert_data_eq!(&errors[0], str!["invalid logging spec 'noNumber'"]);
189201
}
190202

@@ -203,6 +215,7 @@ mod tests {
203215
assert!(filter.is_none());
204216

205217
assert_eq!(errors.len(), 1);
218+
#[cfg(feature = "std")]
206219
assert_data_eq!(&errors[0], str!["invalid logging spec 'wrong'"]);
207220
}
208221

@@ -221,6 +234,7 @@ mod tests {
221234
assert!(filter.is_none());
222235

223236
assert_eq!(errors.len(), 1);
237+
#[cfg(feature = "std")]
224238
assert_data_eq!(&errors[0], str!["invalid logging spec 'wrong'"]);
225239
}
226240

@@ -394,6 +408,7 @@ mod tests {
394408
assert!(filter.is_some() && filter.unwrap().to_string() == "a.c");
395409

396410
assert_eq!(errors.len(), 1);
411+
#[cfg(feature = "std")]
397412
assert_data_eq!(
398413
&errors[0],
399414
str!["invalid logging spec 'crate1::mod1=error=warn'"]
@@ -425,6 +440,7 @@ mod tests {
425440
assert!(filter.is_none());
426441

427442
assert_eq!(errors.len(), 1);
443+
#[cfg(feature = "std")]
428444
assert_data_eq!(
429445
&errors[0],
430446
str!["invalid logging spec 'debug/abc/a.c' (too many '/'s)"]
@@ -446,14 +462,17 @@ mod tests {
446462
assert!(filter.is_none());
447463

448464
assert_eq!(errors.len(), 2);
449-
assert_data_eq!(
450-
&errors[0],
451-
str!["invalid logging spec 'crate1::mod1=warn=info'"]
452-
);
453-
assert_data_eq!(
454-
&errors[1],
455-
str!["invalid logging spec 'crate3=error=error'"]
456-
);
465+
#[cfg(feature = "std")]
466+
{
467+
assert_data_eq!(
468+
&errors[0],
469+
str!["invalid logging spec 'crate1::mod1=warn=info'"]
470+
);
471+
assert_data_eq!(
472+
&errors[1],
473+
str!["invalid logging spec 'crate3=error=error'"]
474+
);
475+
}
457476
}
458477

459478
#[test]
@@ -471,8 +490,11 @@ mod tests {
471490
assert!(filter.is_none());
472491

473492
assert_eq!(errors.len(), 2);
474-
assert_data_eq!(&errors[0], str!["invalid logging spec 'noNumber'"]);
475-
assert_data_eq!(&errors[1], str!["invalid logging spec 'invalid'"]);
493+
#[cfg(feature = "std")]
494+
{
495+
assert_data_eq!(&errors[0], str!["invalid logging spec 'noNumber'"]);
496+
assert_data_eq!(&errors[1], str!["invalid logging spec 'invalid'"]);
497+
}
476498
}
477499

478500
#[test]
@@ -490,18 +512,23 @@ mod tests {
490512
assert!(filter.is_none());
491513

492514
assert_eq!(errors.len(), 2);
493-
assert_data_eq!(
494-
&errors[0],
495-
str!["invalid logging spec 'crate1::mod1=debug=info'"]
496-
);
497-
assert_data_eq!(&errors[1], str!["invalid logging spec 'invalid'"]);
515+
#[cfg(feature = "std")]
516+
{
517+
assert_data_eq!(
518+
&errors[0],
519+
str!["invalid logging spec 'crate1::mod1=debug=info'"]
520+
);
521+
assert_data_eq!(&errors[1], str!["invalid logging spec 'invalid'"]);
522+
}
498523
}
499524

500525
#[test]
501526
fn parse_error_message_single_error() {
527+
#[allow(unused_variables)]
502528
let error = parse_spec("crate1::mod1=debug=info,crate2=debug")
503529
.ok()
504530
.unwrap_err();
531+
#[cfg(feature = "std")]
505532
assert_data_eq!(
506533
error,
507534
str!["error parsing logger filter: invalid logging spec 'crate1::mod1=debug=info'"]
@@ -510,9 +537,11 @@ mod tests {
510537

511538
#[test]
512539
fn parse_error_message_multiple_errors() {
540+
#[allow(unused_variables)]
513541
let error = parse_spec("crate1::mod1=debug=info,crate2=debug,crate3=invalid")
514542
.ok()
515543
.unwrap_err();
544+
#[cfg(feature = "std")]
516545
assert_data_eq!(
517546
error,
518547
str!["error parsing logger filter: invalid logging spec 'crate1::mod1=debug=info'"]

0 commit comments

Comments
 (0)