更新libclamav库1.0.0版本
This commit is contained in:
1
clamav/libclamav_rust/.cargo/vendor/env_logger/.cargo-checksum.json
vendored
Normal file
1
clamav/libclamav_rust/.cargo/vendor/env_logger/.cargo-checksum.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"files":{"CHANGELOG.md":"34c3abc5bfaeb865e9b901c245f7e41f02a96b6be50beef5302458bff548ef3c","Cargo.toml":"a91f488aed0df3b4a1ddc1558f2b2fd05a543f9a37ce28e47548f8d9269ed979","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"c126e3dffb9c9e40c9355b5b0261ca84aa72425c5819bbe13abc40a161c51c78","src/filter/mod.rs":"92e7fd89ef1d5d46851de394a10349230045cb1e97f552f09f42031f372ab3dd","src/filter/regex.rs":"bdf875bac25e089e1e462f5dd01a88678067c24118ecd6268561c6a6af39747d","src/filter/string.rs":"fac54d51189fc0b5d2bff334b7a7e465177b431e3428299e345e1f90062d832e","src/fmt/humantime/extern_impl.rs":"97e0a128275c086b02760a33c22db8524f005994ebb1318a6ac582fd51cf444a","src/fmt/humantime/mod.rs":"f4111c26cf2ffb85c1d639bd7674d55af7e1736e7e98c52f7be3070046a3253f","src/fmt/humantime/shim_impl.rs":"cce9a252abd5952fa109a72b1dfb85a593d237e22606b2b608a32c69184560e9","src/fmt/mod.rs":"eb28817c0db5ed729f516927b981d0833cc3fe8bd2cf48256e03a04400d763df","src/fmt/writer/atty.rs":"09d14097dee61492828daaabdbde9f43251e2cb32e79d66c1c0e63f317761704","src/fmt/writer/mod.rs":"f3fb4adc740a1d9057bd398d751a9af24dead7ac108a8e2c571567778ce0f23e","src/fmt/writer/termcolor/extern_impl.rs":"4f02bdca6ad627856af1ac2eef0813104bd383685a2ff87983da9f7dee8261e3","src/fmt/writer/termcolor/mod.rs":"a790f9391a50cd52be6823e3e55942de13a8d12e23d63765342ae9e8dd6d091c","src/fmt/writer/termcolor/shim_impl.rs":"8e6e7d40782b14e33c6b75b81899a612549c2c7937ce28b48cdc60e1e3f8b855","src/lib.rs":"921561bf8d4efad4ab8938b36bc14e277968bfc364d131203822e64eb6e8265e","tests/init-twice-retains-filter.rs":"be5cd2132342d89ede1f5c4266173bb3c4d51cc22a1847f133d299a1c5430ccb","tests/log-in-log.rs":"29fecc65c1e0d1c22d79c97e7ca843ad44a91f27934148d7a05c48899a3f39d8","tests/log_tls_dtors.rs":"7320667d774a9b05037f7bf273fb2574dec0705707692a9cd2f46f4cd5bc68dd","tests/regexp_filter.rs":"a84263c995b534b6479a1d0abadf63f4f0264958ff86d9173d6b2139b82c4dc5"},"package":"a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"}
|
||||
3
clamav/libclamav_rust/.cargo/vendor/env_logger/CHANGELOG.md
vendored
Normal file
3
clamav/libclamav_rust/.cargo/vendor/env_logger/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
Changes to this crate are tracked via [GitHub Releases][releases].
|
||||
|
||||
[releases]: https://github.com/env-logger-rs/env_logger/releases
|
||||
85
clamav/libclamav_rust/.cargo/vendor/env_logger/Cargo.toml
vendored
Normal file
85
clamav/libclamav_rust/.cargo/vendor/env_logger/Cargo.toml
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "env_logger"
|
||||
version = "0.9.3"
|
||||
include = [
|
||||
"src/**/*",
|
||||
"tests",
|
||||
"LICENSE-*",
|
||||
"README.md",
|
||||
"CHANGELOG.md",
|
||||
]
|
||||
description = """
|
||||
A logging implementation for `log` which is configured via an environment
|
||||
variable.
|
||||
"""
|
||||
documentation = "https://docs.rs/env_logger"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"logging",
|
||||
"log",
|
||||
"logger",
|
||||
]
|
||||
categories = ["development-tools::debugging"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/env-logger-rs/env_logger/"
|
||||
|
||||
[[test]]
|
||||
name = "regexp_filter"
|
||||
harness = false
|
||||
|
||||
[[test]]
|
||||
name = "log-in-log"
|
||||
harness = false
|
||||
|
||||
[[test]]
|
||||
name = "log_tls_dtors"
|
||||
harness = false
|
||||
|
||||
[[test]]
|
||||
name = "init-twice-retains-filter"
|
||||
harness = false
|
||||
|
||||
[dependencies.atty]
|
||||
version = "0.2.5"
|
||||
optional = true
|
||||
|
||||
[dependencies.humantime]
|
||||
version = "2.0.0"
|
||||
optional = true
|
||||
|
||||
[dependencies.log]
|
||||
version = "0.4.8"
|
||||
features = ["std"]
|
||||
|
||||
[dependencies.regex]
|
||||
version = "1.0.3"
|
||||
features = [
|
||||
"std",
|
||||
"perf",
|
||||
]
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dependencies.termcolor]
|
||||
version = "1.1.1"
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
default = [
|
||||
"termcolor",
|
||||
"atty",
|
||||
"humantime",
|
||||
"regex",
|
||||
]
|
||||
201
clamav/libclamav_rust/.cargo/vendor/env_logger/LICENSE-APACHE
vendored
Normal file
201
clamav/libclamav_rust/.cargo/vendor/env_logger/LICENSE-APACHE
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
23
clamav/libclamav_rust/.cargo/vendor/env_logger/LICENSE-MIT
vendored
Normal file
23
clamav/libclamav_rust/.cargo/vendor/env_logger/LICENSE-MIT
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
183
clamav/libclamav_rust/.cargo/vendor/env_logger/README.md
vendored
Normal file
183
clamav/libclamav_rust/.cargo/vendor/env_logger/README.md
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
# env_logger
|
||||
|
||||
[](https://crates.io/crates/env_logger)
|
||||
[](https://docs.rs/env_logger)
|
||||
[](https://env-logger-rs.github.io/env_logger/env_logger/index.html)
|
||||
|
||||
Implements a logger that can be configured via environment variables.
|
||||
|
||||
## Usage
|
||||
|
||||
### In libraries
|
||||
|
||||
`env_logger` makes sense when used in executables (binary projects). Libraries should use the [`log`](https://docs.rs/log) crate instead.
|
||||
|
||||
### In executables
|
||||
|
||||
It must be added along with `log` to the project dependencies:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
log = "0.4.0"
|
||||
env_logger = "0.9.0"
|
||||
```
|
||||
|
||||
`env_logger` must be initialized as early as possible in the project. After it's initialized, you can use the `log` macros to do actual logging.
|
||||
|
||||
```rust
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
||||
info!("starting up");
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Then when running the executable, specify a value for the **`RUST_LOG`**
|
||||
environment variable that corresponds with the log messages you want to show.
|
||||
|
||||
```bash
|
||||
$ RUST_LOG=info ./main
|
||||
[2018-11-03T06:09:06Z INFO default] starting up
|
||||
```
|
||||
|
||||
The letter case is not significant for the logging level names; e.g., `debug`,
|
||||
`DEBUG`, and `dEbuG` all represent the same logging level. Therefore, the
|
||||
previous example could also have been written this way, specifying the log
|
||||
level as `INFO` rather than as `info`:
|
||||
|
||||
```bash
|
||||
$ RUST_LOG=INFO ./main
|
||||
[2018-11-03T06:09:06Z INFO default] starting up
|
||||
```
|
||||
|
||||
So which form should you use? For consistency, our convention is to use lower
|
||||
case names. Where our docs do use other forms, they do so in the context of
|
||||
specific examples, so you won't be surprised if you see similar usage in the
|
||||
wild.
|
||||
|
||||
The log levels that may be specified correspond to the [`log::Level`][level-enum]
|
||||
enum from the `log` crate. They are:
|
||||
|
||||
* `error`
|
||||
* `warn`
|
||||
* `info`
|
||||
* `debug`
|
||||
* `trace`
|
||||
|
||||
[level-enum]: https://docs.rs/log/latest/log/enum.Level.html "log::Level (docs.rs)"
|
||||
|
||||
There is also a pseudo logging level, `off`, which may be specified to disable
|
||||
all logging for a given module or for the entire application. As with the
|
||||
logging levels, the letter case is not significant.
|
||||
|
||||
`env_logger` can be configured in other ways besides an environment variable. See [the examples](https://github.com/env-logger-rs/env_logger/tree/main/examples) for more approaches.
|
||||
|
||||
### In tests
|
||||
|
||||
Tests can use the `env_logger` crate to see log messages generated during that test:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
log = "0.4.0"
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.9.0"
|
||||
```
|
||||
|
||||
```rust
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
fn add_one(num: i32) -> i32 {
|
||||
info!("add_one called with {}", num);
|
||||
num + 1
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn init() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_adds_one() {
|
||||
init();
|
||||
|
||||
info!("can log from the test too");
|
||||
assert_eq!(3, add_one(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_handles_negative_numbers() {
|
||||
init();
|
||||
|
||||
info!("logging from another test");
|
||||
assert_eq!(-7, add_one(-8));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Assuming the module under test is called `my_lib`, running the tests with the
|
||||
`RUST_LOG` filtering to info messages from this module looks like:
|
||||
|
||||
```bash
|
||||
$ RUST_LOG=my_lib=info cargo test
|
||||
Running target/debug/my_lib-...
|
||||
|
||||
running 2 tests
|
||||
[INFO my_lib::tests] logging from another test
|
||||
[INFO my_lib] add_one called with -8
|
||||
test tests::it_handles_negative_numbers ... ok
|
||||
[INFO my_lib::tests] can log from the test too
|
||||
[INFO my_lib] add_one called with 2
|
||||
test tests::it_adds_one ... ok
|
||||
|
||||
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured
|
||||
```
|
||||
|
||||
Note that `env_logger::try_init()` needs to be called in each test in which you
|
||||
want to enable logging. Additionally, the default behavior of tests to
|
||||
run in parallel means that logging output may be interleaved with test output.
|
||||
Either run tests in a single thread by specifying `RUST_TEST_THREADS=1` or by
|
||||
running one test by specifying its name as an argument to the test binaries as
|
||||
directed by the `cargo test` help docs:
|
||||
|
||||
```bash
|
||||
$ RUST_LOG=my_lib=info cargo test it_adds_one
|
||||
Running target/debug/my_lib-...
|
||||
|
||||
running 1 test
|
||||
[INFO my_lib::tests] can log from the test too
|
||||
[INFO my_lib] add_one called with 2
|
||||
test tests::it_adds_one ... ok
|
||||
|
||||
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
|
||||
```
|
||||
|
||||
## Configuring log target
|
||||
|
||||
By default, `env_logger` logs to stderr. If you want to log to stdout instead,
|
||||
you can use the `Builder` to change the log target:
|
||||
|
||||
```rust
|
||||
use std::env;
|
||||
use env_logger::{Builder, Target};
|
||||
|
||||
let mut builder = Builder::from_default_env();
|
||||
builder.target(Target::Stdout);
|
||||
|
||||
builder.init();
|
||||
```
|
||||
|
||||
## Stability of the default format
|
||||
|
||||
The default format won't optimise for long-term stability, and explicitly makes no guarantees about the stability of its output across major, minor or patch version bumps during `0.x`.
|
||||
|
||||
If you want to capture or interpret the output of `env_logger` programmatically then you should use a custom format.
|
||||
868
clamav/libclamav_rust/.cargo/vendor/env_logger/src/filter/mod.rs
vendored
Normal file
868
clamav/libclamav_rust/.cargo/vendor/env_logger/src/filter/mod.rs
vendored
Normal file
@@ -0,0 +1,868 @@
|
||||
//! Filtering for log records.
|
||||
//!
|
||||
//! This module contains the log filtering used by `env_logger` to match records.
|
||||
//! You can use the `Filter` type in your own logger implementation to use the same
|
||||
//! filter parsing and matching as `env_logger`. For more details about the format
|
||||
//! for directive strings see [Enabling Logging].
|
||||
//!
|
||||
//! ## Using `env_logger` in your own logger
|
||||
//!
|
||||
//! You can use `env_logger`'s filtering functionality with your own logger.
|
||||
//! Call [`Builder::parse`] to parse directives from a string when constructing
|
||||
//! your logger. Call [`Filter::matches`] to check whether a record should be
|
||||
//! logged based on the parsed filters when log records are received.
|
||||
//!
|
||||
//! ```
|
||||
//! extern crate log;
|
||||
//! extern crate env_logger;
|
||||
//! use env_logger::filter::Filter;
|
||||
//! use log::{Log, Metadata, Record};
|
||||
//!
|
||||
//! struct MyLogger {
|
||||
//! filter: Filter
|
||||
//! }
|
||||
//!
|
||||
//! impl MyLogger {
|
||||
//! fn new() -> MyLogger {
|
||||
//! use env_logger::filter::Builder;
|
||||
//! let mut builder = Builder::new();
|
||||
//!
|
||||
//! // Parse a directives string from an environment variable
|
||||
//! if let Ok(ref filter) = std::env::var("MY_LOG_LEVEL") {
|
||||
//! builder.parse(filter);
|
||||
//! }
|
||||
//!
|
||||
//! MyLogger {
|
||||
//! filter: builder.build()
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! impl Log for MyLogger {
|
||||
//! fn enabled(&self, metadata: &Metadata) -> bool {
|
||||
//! self.filter.enabled(metadata)
|
||||
//! }
|
||||
//!
|
||||
//! fn log(&self, record: &Record) {
|
||||
//! // Check if the record is matched by the filter
|
||||
//! if self.filter.matches(record) {
|
||||
//! println!("{:?}", record);
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! fn flush(&self) {}
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! [Enabling Logging]: ../index.html#enabling-logging
|
||||
//! [`Builder::parse`]: struct.Builder.html#method.parse
|
||||
//! [`Filter::matches`]: struct.Filter.html#method.matches
|
||||
|
||||
use log::{Level, LevelFilter, Metadata, Record};
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
|
||||
#[cfg(feature = "regex")]
|
||||
#[path = "regex.rs"]
|
||||
mod inner;
|
||||
|
||||
#[cfg(not(feature = "regex"))]
|
||||
#[path = "string.rs"]
|
||||
mod inner;
|
||||
|
||||
/// A log filter.
|
||||
///
|
||||
/// This struct can be used to determine whether or not a log record
|
||||
/// should be written to the output.
|
||||
/// Use the [`Builder`] type to parse and construct a `Filter`.
|
||||
///
|
||||
/// [`Builder`]: struct.Builder.html
|
||||
pub struct Filter {
|
||||
directives: Vec<Directive>,
|
||||
filter: Option<inner::Filter>,
|
||||
}
|
||||
|
||||
/// A builder for a log filter.
|
||||
///
|
||||
/// It can be used to parse a set of directives from a string before building
|
||||
/// a [`Filter`] instance.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```
|
||||
/// # #[macro_use] extern crate log;
|
||||
/// # use std::env;
|
||||
/// use env_logger::filter::Builder;
|
||||
///
|
||||
/// let mut builder = Builder::new();
|
||||
///
|
||||
/// // Parse a logging filter from an environment variable.
|
||||
/// if let Ok(rust_log) = env::var("RUST_LOG") {
|
||||
/// builder.parse(&rust_log);
|
||||
/// }
|
||||
///
|
||||
/// let filter = builder.build();
|
||||
/// ```
|
||||
///
|
||||
/// [`Filter`]: struct.Filter.html
|
||||
pub struct Builder {
|
||||
directives: HashMap<Option<String>, LevelFilter>,
|
||||
filter: Option<inner::Filter>,
|
||||
built: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Directive {
|
||||
name: Option<String>,
|
||||
level: LevelFilter,
|
||||
}
|
||||
|
||||
impl Filter {
|
||||
/// Returns the maximum `LevelFilter` that this filter instance is
|
||||
/// configured to output.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use log::LevelFilter;
|
||||
/// use env_logger::filter::Builder;
|
||||
///
|
||||
/// let mut builder = Builder::new();
|
||||
/// builder.filter(Some("module1"), LevelFilter::Info);
|
||||
/// builder.filter(Some("module2"), LevelFilter::Error);
|
||||
///
|
||||
/// let filter = builder.build();
|
||||
/// assert_eq!(filter.filter(), LevelFilter::Info);
|
||||
/// ```
|
||||
pub fn filter(&self) -> LevelFilter {
|
||||
self.directives
|
||||
.iter()
|
||||
.map(|d| d.level)
|
||||
.max()
|
||||
.unwrap_or(LevelFilter::Off)
|
||||
}
|
||||
|
||||
/// Checks if this record matches the configured filter.
|
||||
pub fn matches(&self, record: &Record) -> bool {
|
||||
if !self.enabled(record.metadata()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(filter) = self.filter.as_ref() {
|
||||
if !filter.is_match(&record.args().to_string()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
/// Determines if a log message with the specified metadata would be logged.
|
||||
pub fn enabled(&self, metadata: &Metadata) -> bool {
|
||||
let level = metadata.level();
|
||||
let target = metadata.target();
|
||||
|
||||
enabled(&self.directives, level, target)
|
||||
}
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
/// Initializes the filter builder with defaults.
|
||||
pub fn new() -> Builder {
|
||||
Builder {
|
||||
directives: HashMap::new(),
|
||||
filter: None,
|
||||
built: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes the filter builder from an environment.
|
||||
pub fn from_env(env: &str) -> Builder {
|
||||
let mut builder = Builder::new();
|
||||
|
||||
if let Ok(s) = env::var(env) {
|
||||
builder.parse(&s);
|
||||
}
|
||||
|
||||
builder
|
||||
}
|
||||
|
||||
/// Adds a directive to the filter for a specific module.
|
||||
pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self {
|
||||
self.filter(Some(module), level)
|
||||
}
|
||||
|
||||
/// Adds a directive to the filter for all modules.
|
||||
pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self {
|
||||
self.filter(None, level)
|
||||
}
|
||||
|
||||
/// Adds a directive to the filter.
|
||||
///
|
||||
/// The given module (if any) will log at most the specified level provided.
|
||||
/// If no module is provided then the filter will apply to all log messages.
|
||||
pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self {
|
||||
self.directives.insert(module.map(|s| s.to_string()), level);
|
||||
self
|
||||
}
|
||||
|
||||
/// Parses the directives string.
|
||||
///
|
||||
/// See the [Enabling Logging] section for more details.
|
||||
///
|
||||
/// [Enabling Logging]: ../index.html#enabling-logging
|
||||
pub fn parse(&mut self, filters: &str) -> &mut Self {
|
||||
let (directives, filter) = parse_spec(filters);
|
||||
|
||||
self.filter = filter;
|
||||
|
||||
for directive in directives {
|
||||
self.directives.insert(directive.name, directive.level);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Build a log filter.
|
||||
pub fn build(&mut self) -> Filter {
|
||||
assert!(!self.built, "attempt to re-use consumed builder");
|
||||
self.built = true;
|
||||
|
||||
let mut directives = Vec::new();
|
||||
if self.directives.is_empty() {
|
||||
// Adds the default filter if none exist
|
||||
directives.push(Directive {
|
||||
name: None,
|
||||
level: LevelFilter::Error,
|
||||
});
|
||||
} else {
|
||||
// Consume map of directives.
|
||||
let directives_map = mem::take(&mut self.directives);
|
||||
directives = directives_map
|
||||
.into_iter()
|
||||
.map(|(name, level)| Directive { name, level })
|
||||
.collect();
|
||||
// Sort the directives by length of their name, this allows a
|
||||
// little more efficient lookup at runtime.
|
||||
directives.sort_by(|a, b| {
|
||||
let alen = a.name.as_ref().map(|a| a.len()).unwrap_or(0);
|
||||
let blen = b.name.as_ref().map(|b| b.len()).unwrap_or(0);
|
||||
alen.cmp(&blen)
|
||||
});
|
||||
}
|
||||
|
||||
Filter {
|
||||
directives: mem::take(&mut directives),
|
||||
filter: mem::replace(&mut self.filter, None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Builder {
|
||||
fn default() -> Self {
|
||||
Builder::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Filter {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Filter")
|
||||
.field("filter", &self.filter)
|
||||
.field("directives", &self.directives)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Builder {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.built {
|
||||
f.debug_struct("Filter").field("built", &true).finish()
|
||||
} else {
|
||||
f.debug_struct("Filter")
|
||||
.field("filter", &self.filter)
|
||||
.field("directives", &self.directives)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=error/foo")
|
||||
/// and return a vector with log directives.
|
||||
fn parse_spec(spec: &str) -> (Vec<Directive>, Option<inner::Filter>) {
|
||||
let mut dirs = Vec::new();
|
||||
|
||||
let mut parts = spec.split('/');
|
||||
let mods = parts.next();
|
||||
let filter = parts.next();
|
||||
if parts.next().is_some() {
|
||||
eprintln!(
|
||||
"warning: invalid logging spec '{}', \
|
||||
ignoring it (too many '/'s)",
|
||||
spec
|
||||
);
|
||||
return (dirs, None);
|
||||
}
|
||||
if let Some(m) = mods {
|
||||
for s in m.split(',').map(|ss| ss.trim()) {
|
||||
if s.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let mut parts = s.split('=');
|
||||
let (log_level, name) =
|
||||
match (parts.next(), parts.next().map(|s| s.trim()), parts.next()) {
|
||||
(Some(part0), None, None) => {
|
||||
// if the single argument is a log-level string or number,
|
||||
// treat that as a global fallback
|
||||
match part0.parse() {
|
||||
Ok(num) => (num, None),
|
||||
Err(_) => (LevelFilter::max(), Some(part0)),
|
||||
}
|
||||
}
|
||||
(Some(part0), Some(""), None) => (LevelFilter::max(), Some(part0)),
|
||||
(Some(part0), Some(part1), None) => match part1.parse() {
|
||||
Ok(num) => (num, Some(part0)),
|
||||
_ => {
|
||||
eprintln!(
|
||||
"warning: invalid logging spec '{}', \
|
||||
ignoring it",
|
||||
part1
|
||||
);
|
||||
continue;
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
eprintln!(
|
||||
"warning: invalid logging spec '{}', \
|
||||
ignoring it",
|
||||
s
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
dirs.push(Directive {
|
||||
name: name.map(|s| s.to_string()),
|
||||
level: log_level,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let filter = filter.and_then(|filter| match inner::Filter::new(filter) {
|
||||
Ok(re) => Some(re),
|
||||
Err(e) => {
|
||||
eprintln!("warning: invalid regex filter - {}", e);
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
(dirs, filter)
|
||||
}
|
||||
|
||||
// Check whether a level and target are enabled by the set of directives.
|
||||
fn enabled(directives: &[Directive], level: Level, target: &str) -> bool {
|
||||
// Search for the longest match, the vector is assumed to be pre-sorted.
|
||||
for directive in directives.iter().rev() {
|
||||
match directive.name {
|
||||
Some(ref name) if !target.starts_with(&**name) => {}
|
||||
Some(..) | None => return level <= directive.level,
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use log::{Level, LevelFilter};
|
||||
|
||||
use super::{enabled, parse_spec, Builder, Directive, Filter};
|
||||
|
||||
fn make_logger_filter(dirs: Vec<Directive>) -> Filter {
|
||||
let mut logger = Builder::new().build();
|
||||
logger.directives = dirs;
|
||||
logger
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filter_info() {
|
||||
let logger = Builder::new().filter(None, LevelFilter::Info).build();
|
||||
assert!(enabled(&logger.directives, Level::Info, "crate1"));
|
||||
assert!(!enabled(&logger.directives, Level::Debug, "crate1"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filter_beginning_longest_match() {
|
||||
let logger = Builder::new()
|
||||
.filter(Some("crate2"), LevelFilter::Info)
|
||||
.filter(Some("crate2::mod"), LevelFilter::Debug)
|
||||
.filter(Some("crate1::mod1"), LevelFilter::Warn)
|
||||
.build();
|
||||
assert!(enabled(&logger.directives, Level::Debug, "crate2::mod1"));
|
||||
assert!(!enabled(&logger.directives, Level::Debug, "crate2"));
|
||||
}
|
||||
|
||||
// Some of our tests are only correct or complete when they cover the full
|
||||
// universe of variants for log::Level. In the unlikely event that a new
|
||||
// variant is added in the future, this test will detect the scenario and
|
||||
// alert us to the need to review and update the tests. In such a
|
||||
// situation, this test will fail to compile, and the error message will
|
||||
// look something like this:
|
||||
//
|
||||
// error[E0004]: non-exhaustive patterns: `NewVariant` not covered
|
||||
// --> src/filter/mod.rs:413:15
|
||||
// |
|
||||
// 413 | match level_universe {
|
||||
// | ^^^^^^^^^^^^^^ pattern `NewVariant` not covered
|
||||
#[test]
|
||||
fn ensure_tests_cover_level_universe() {
|
||||
let level_universe: Level = Level::Trace; // use of trace variant is arbitrary
|
||||
match level_universe {
|
||||
Level::Error | Level::Warn | Level::Info | Level::Debug | Level::Trace => (),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_default() {
|
||||
let logger = Builder::new().parse("info,crate1::mod1=warn").build();
|
||||
assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1"));
|
||||
assert!(enabled(&logger.directives, Level::Info, "crate2::mod2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_default_bare_level_off_lc() {
|
||||
let logger = Builder::new().parse("off").build();
|
||||
assert!(!enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_default_bare_level_off_uc() {
|
||||
let logger = Builder::new().parse("OFF").build();
|
||||
assert!(!enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_default_bare_level_error_lc() {
|
||||
let logger = Builder::new().parse("error").build();
|
||||
assert!(enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_default_bare_level_error_uc() {
|
||||
let logger = Builder::new().parse("ERROR").build();
|
||||
assert!(enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_default_bare_level_warn_lc() {
|
||||
let logger = Builder::new().parse("warn").build();
|
||||
assert!(enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_default_bare_level_warn_uc() {
|
||||
let logger = Builder::new().parse("WARN").build();
|
||||
assert!(enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_default_bare_level_info_lc() {
|
||||
let logger = Builder::new().parse("info").build();
|
||||
assert!(enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_default_bare_level_info_uc() {
|
||||
let logger = Builder::new().parse("INFO").build();
|
||||
assert!(enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_default_bare_level_debug_lc() {
|
||||
let logger = Builder::new().parse("debug").build();
|
||||
assert!(enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_default_bare_level_debug_uc() {
|
||||
let logger = Builder::new().parse("DEBUG").build();
|
||||
assert!(enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_default_bare_level_trace_lc() {
|
||||
let logger = Builder::new().parse("trace").build();
|
||||
assert!(enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_default_bare_level_trace_uc() {
|
||||
let logger = Builder::new().parse("TRACE").build();
|
||||
assert!(enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
|
||||
// In practice, the desired log level is typically specified by a token
|
||||
// that is either all lowercase (e.g., 'trace') or all uppercase (.e.g,
|
||||
// 'TRACE'), but this tests serves as a reminder that
|
||||
// log::Level::from_str() ignores all case variants.
|
||||
#[test]
|
||||
fn parse_default_bare_level_debug_mixed() {
|
||||
{
|
||||
let logger = Builder::new().parse("Debug").build();
|
||||
assert!(enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
{
|
||||
let logger = Builder::new().parse("debuG").build();
|
||||
assert!(enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
{
|
||||
let logger = Builder::new().parse("deBug").build();
|
||||
assert!(enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
{
|
||||
let logger = Builder::new().parse("DeBuG").build(); // LaTeX flavor!
|
||||
assert!(enabled(&logger.directives, Level::Error, ""));
|
||||
assert!(enabled(&logger.directives, Level::Warn, ""));
|
||||
assert!(enabled(&logger.directives, Level::Info, ""));
|
||||
assert!(enabled(&logger.directives, Level::Debug, ""));
|
||||
assert!(!enabled(&logger.directives, Level::Trace, ""));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn match_full_path() {
|
||||
let logger = make_logger_filter(vec![
|
||||
Directive {
|
||||
name: Some("crate2".to_string()),
|
||||
level: LevelFilter::Info,
|
||||
},
|
||||
Directive {
|
||||
name: Some("crate1::mod1".to_string()),
|
||||
level: LevelFilter::Warn,
|
||||
},
|
||||
]);
|
||||
assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1"));
|
||||
assert!(!enabled(&logger.directives, Level::Info, "crate1::mod1"));
|
||||
assert!(enabled(&logger.directives, Level::Info, "crate2"));
|
||||
assert!(!enabled(&logger.directives, Level::Debug, "crate2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_match() {
|
||||
let logger = make_logger_filter(vec![
|
||||
Directive {
|
||||
name: Some("crate2".to_string()),
|
||||
level: LevelFilter::Info,
|
||||
},
|
||||
Directive {
|
||||
name: Some("crate1::mod1".to_string()),
|
||||
level: LevelFilter::Warn,
|
||||
},
|
||||
]);
|
||||
assert!(!enabled(&logger.directives, Level::Warn, "crate3"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn match_beginning() {
|
||||
let logger = make_logger_filter(vec![
|
||||
Directive {
|
||||
name: Some("crate2".to_string()),
|
||||
level: LevelFilter::Info,
|
||||
},
|
||||
Directive {
|
||||
name: Some("crate1::mod1".to_string()),
|
||||
level: LevelFilter::Warn,
|
||||
},
|
||||
]);
|
||||
assert!(enabled(&logger.directives, Level::Info, "crate2::mod1"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn match_beginning_longest_match() {
|
||||
let logger = make_logger_filter(vec![
|
||||
Directive {
|
||||
name: Some("crate2".to_string()),
|
||||
level: LevelFilter::Info,
|
||||
},
|
||||
Directive {
|
||||
name: Some("crate2::mod".to_string()),
|
||||
level: LevelFilter::Debug,
|
||||
},
|
||||
Directive {
|
||||
name: Some("crate1::mod1".to_string()),
|
||||
level: LevelFilter::Warn,
|
||||
},
|
||||
]);
|
||||
assert!(enabled(&logger.directives, Level::Debug, "crate2::mod1"));
|
||||
assert!(!enabled(&logger.directives, Level::Debug, "crate2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn match_default() {
|
||||
let logger = make_logger_filter(vec![
|
||||
Directive {
|
||||
name: None,
|
||||
level: LevelFilter::Info,
|
||||
},
|
||||
Directive {
|
||||
name: Some("crate1::mod1".to_string()),
|
||||
level: LevelFilter::Warn,
|
||||
},
|
||||
]);
|
||||
assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1"));
|
||||
assert!(enabled(&logger.directives, Level::Info, "crate2::mod2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zero_level() {
|
||||
let logger = make_logger_filter(vec![
|
||||
Directive {
|
||||
name: None,
|
||||
level: LevelFilter::Info,
|
||||
},
|
||||
Directive {
|
||||
name: Some("crate1::mod1".to_string()),
|
||||
level: LevelFilter::Off,
|
||||
},
|
||||
]);
|
||||
assert!(!enabled(&logger.directives, Level::Error, "crate1::mod1"));
|
||||
assert!(enabled(&logger.directives, Level::Info, "crate2::mod2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_valid() {
|
||||
let (dirs, filter) = parse_spec("crate1::mod1=error,crate1::mod2,crate2=debug");
|
||||
assert_eq!(dirs.len(), 3);
|
||||
assert_eq!(dirs[0].name, Some("crate1::mod1".to_string()));
|
||||
assert_eq!(dirs[0].level, LevelFilter::Error);
|
||||
|
||||
assert_eq!(dirs[1].name, Some("crate1::mod2".to_string()));
|
||||
assert_eq!(dirs[1].level, LevelFilter::max());
|
||||
|
||||
assert_eq!(dirs[2].name, Some("crate2".to_string()));
|
||||
assert_eq!(dirs[2].level, LevelFilter::Debug);
|
||||
assert!(filter.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_invalid_crate() {
|
||||
// test parse_spec with multiple = in specification
|
||||
let (dirs, filter) = parse_spec("crate1::mod1=warn=info,crate2=debug");
|
||||
assert_eq!(dirs.len(), 1);
|
||||
assert_eq!(dirs[0].name, Some("crate2".to_string()));
|
||||
assert_eq!(dirs[0].level, LevelFilter::Debug);
|
||||
assert!(filter.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_invalid_level() {
|
||||
// test parse_spec with 'noNumber' as log level
|
||||
let (dirs, filter) = parse_spec("crate1::mod1=noNumber,crate2=debug");
|
||||
assert_eq!(dirs.len(), 1);
|
||||
assert_eq!(dirs[0].name, Some("crate2".to_string()));
|
||||
assert_eq!(dirs[0].level, LevelFilter::Debug);
|
||||
assert!(filter.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_string_level() {
|
||||
// test parse_spec with 'warn' as log level
|
||||
let (dirs, filter) = parse_spec("crate1::mod1=wrong,crate2=warn");
|
||||
assert_eq!(dirs.len(), 1);
|
||||
assert_eq!(dirs[0].name, Some("crate2".to_string()));
|
||||
assert_eq!(dirs[0].level, LevelFilter::Warn);
|
||||
assert!(filter.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_empty_level() {
|
||||
// test parse_spec with '' as log level
|
||||
let (dirs, filter) = parse_spec("crate1::mod1=wrong,crate2=");
|
||||
assert_eq!(dirs.len(), 1);
|
||||
assert_eq!(dirs[0].name, Some("crate2".to_string()));
|
||||
assert_eq!(dirs[0].level, LevelFilter::max());
|
||||
assert!(filter.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_empty_level_isolated() {
|
||||
// test parse_spec with "" as log level (and the entire spec str)
|
||||
let (dirs, filter) = parse_spec(""); // should be ignored
|
||||
assert_eq!(dirs.len(), 0);
|
||||
assert!(filter.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_blank_level_isolated() {
|
||||
// test parse_spec with a white-space-only string specified as the log
|
||||
// level (and the entire spec str)
|
||||
let (dirs, filter) = parse_spec(" "); // should be ignored
|
||||
assert_eq!(dirs.len(), 0);
|
||||
assert!(filter.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_blank_level_isolated_comma_only() {
|
||||
// The spec should contain zero or more comma-separated string slices,
|
||||
// so a comma-only string should be interpretted as two empty strings
|
||||
// (which should both be treated as invalid, so ignored).
|
||||
let (dirs, filter) = parse_spec(","); // should be ignored
|
||||
assert_eq!(dirs.len(), 0);
|
||||
assert!(filter.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_blank_level_isolated_comma_blank() {
|
||||
// The spec should contain zero or more comma-separated string slices,
|
||||
// so this bogus spec should be interpretted as containing one empty
|
||||
// string and one blank string. Both should both be treated as
|
||||
// invalid, so ignored.
|
||||
let (dirs, filter) = parse_spec(", "); // should be ignored
|
||||
assert_eq!(dirs.len(), 0);
|
||||
assert!(filter.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_blank_level_isolated_blank_comma() {
|
||||
// The spec should contain zero or more comma-separated string slices,
|
||||
// so this bogus spec should be interpretted as containing one blank
|
||||
// string and one empty string. Both should both be treated as
|
||||
// invalid, so ignored.
|
||||
let (dirs, filter) = parse_spec(" ,"); // should be ignored
|
||||
assert_eq!(dirs.len(), 0);
|
||||
assert!(filter.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_global() {
|
||||
// test parse_spec with no crate
|
||||
let (dirs, filter) = parse_spec("warn,crate2=debug");
|
||||
assert_eq!(dirs.len(), 2);
|
||||
assert_eq!(dirs[0].name, None);
|
||||
assert_eq!(dirs[0].level, LevelFilter::Warn);
|
||||
assert_eq!(dirs[1].name, Some("crate2".to_string()));
|
||||
assert_eq!(dirs[1].level, LevelFilter::Debug);
|
||||
assert!(filter.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_global_bare_warn_lc() {
|
||||
// test parse_spec with no crate, in isolation, all lowercase
|
||||
let (dirs, filter) = parse_spec("warn");
|
||||
assert_eq!(dirs.len(), 1);
|
||||
assert_eq!(dirs[0].name, None);
|
||||
assert_eq!(dirs[0].level, LevelFilter::Warn);
|
||||
assert!(filter.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_global_bare_warn_uc() {
|
||||
// test parse_spec with no crate, in isolation, all uppercase
|
||||
let (dirs, filter) = parse_spec("WARN");
|
||||
assert_eq!(dirs.len(), 1);
|
||||
assert_eq!(dirs[0].name, None);
|
||||
assert_eq!(dirs[0].level, LevelFilter::Warn);
|
||||
assert!(filter.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_global_bare_warn_mixed() {
|
||||
// test parse_spec with no crate, in isolation, mixed case
|
||||
let (dirs, filter) = parse_spec("wArN");
|
||||
assert_eq!(dirs.len(), 1);
|
||||
assert_eq!(dirs[0].name, None);
|
||||
assert_eq!(dirs[0].level, LevelFilter::Warn);
|
||||
assert!(filter.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_valid_filter() {
|
||||
let (dirs, filter) = parse_spec("crate1::mod1=error,crate1::mod2,crate2=debug/abc");
|
||||
assert_eq!(dirs.len(), 3);
|
||||
assert_eq!(dirs[0].name, Some("crate1::mod1".to_string()));
|
||||
assert_eq!(dirs[0].level, LevelFilter::Error);
|
||||
|
||||
assert_eq!(dirs[1].name, Some("crate1::mod2".to_string()));
|
||||
assert_eq!(dirs[1].level, LevelFilter::max());
|
||||
|
||||
assert_eq!(dirs[2].name, Some("crate2".to_string()));
|
||||
assert_eq!(dirs[2].level, LevelFilter::Debug);
|
||||
assert!(filter.is_some() && filter.unwrap().to_string() == "abc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_invalid_crate_filter() {
|
||||
let (dirs, filter) = parse_spec("crate1::mod1=error=warn,crate2=debug/a.c");
|
||||
assert_eq!(dirs.len(), 1);
|
||||
assert_eq!(dirs[0].name, Some("crate2".to_string()));
|
||||
assert_eq!(dirs[0].level, LevelFilter::Debug);
|
||||
assert!(filter.is_some() && filter.unwrap().to_string() == "a.c");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_spec_empty_with_filter() {
|
||||
let (dirs, filter) = parse_spec("crate1/a*c");
|
||||
assert_eq!(dirs.len(), 1);
|
||||
assert_eq!(dirs[0].name, Some("crate1".to_string()));
|
||||
assert_eq!(dirs[0].level, LevelFilter::max());
|
||||
assert!(filter.is_some() && filter.unwrap().to_string() == "a*c");
|
||||
}
|
||||
}
|
||||
29
clamav/libclamav_rust/.cargo/vendor/env_logger/src/filter/regex.rs
vendored
Normal file
29
clamav/libclamav_rust/.cargo/vendor/env_logger/src/filter/regex.rs
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
extern crate regex;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use self::regex::Regex;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Filter {
|
||||
inner: Regex,
|
||||
}
|
||||
|
||||
impl Filter {
|
||||
pub fn new(spec: &str) -> Result<Filter, String> {
|
||||
match Regex::new(spec) {
|
||||
Ok(r) => Ok(Filter { inner: r }),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_match(&self, s: &str) -> bool {
|
||||
self.inner.is_match(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Filter {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.inner.fmt(f)
|
||||
}
|
||||
}
|
||||
24
clamav/libclamav_rust/.cargo/vendor/env_logger/src/filter/string.rs
vendored
Normal file
24
clamav/libclamav_rust/.cargo/vendor/env_logger/src/filter/string.rs
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Filter {
|
||||
inner: String,
|
||||
}
|
||||
|
||||
impl Filter {
|
||||
pub fn new(spec: &str) -> Result<Filter, String> {
|
||||
Ok(Filter {
|
||||
inner: spec.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_match(&self, s: &str) -> bool {
|
||||
s.contains(&self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Filter {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.inner.fmt(f)
|
||||
}
|
||||
}
|
||||
118
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/humantime/extern_impl.rs
vendored
Normal file
118
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/humantime/extern_impl.rs
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
use std::fmt;
|
||||
use std::time::SystemTime;
|
||||
|
||||
use humantime::{
|
||||
format_rfc3339_micros, format_rfc3339_millis, format_rfc3339_nanos, format_rfc3339_seconds,
|
||||
};
|
||||
|
||||
use crate::fmt::{Formatter, TimestampPrecision};
|
||||
|
||||
pub(in crate::fmt) mod glob {
|
||||
pub use super::*;
|
||||
}
|
||||
|
||||
impl Formatter {
|
||||
/// Get a [`Timestamp`] for the current date and time in UTC.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Include the current timestamp with the log record:
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Write;
|
||||
///
|
||||
/// let mut builder = env_logger::Builder::new();
|
||||
///
|
||||
/// builder.format(|buf, record| {
|
||||
/// let ts = buf.timestamp();
|
||||
///
|
||||
/// writeln!(buf, "{}: {}: {}", ts, record.level(), record.args())
|
||||
/// });
|
||||
/// ```
|
||||
///
|
||||
/// [`Timestamp`]: struct.Timestamp.html
|
||||
pub fn timestamp(&self) -> Timestamp {
|
||||
Timestamp {
|
||||
time: SystemTime::now(),
|
||||
precision: TimestampPrecision::Seconds,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a [`Timestamp`] for the current date and time in UTC with full
|
||||
/// second precision.
|
||||
pub fn timestamp_seconds(&self) -> Timestamp {
|
||||
Timestamp {
|
||||
time: SystemTime::now(),
|
||||
precision: TimestampPrecision::Seconds,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a [`Timestamp`] for the current date and time in UTC with
|
||||
/// millisecond precision.
|
||||
pub fn timestamp_millis(&self) -> Timestamp {
|
||||
Timestamp {
|
||||
time: SystemTime::now(),
|
||||
precision: TimestampPrecision::Millis,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a [`Timestamp`] for the current date and time in UTC with
|
||||
/// microsecond precision.
|
||||
pub fn timestamp_micros(&self) -> Timestamp {
|
||||
Timestamp {
|
||||
time: SystemTime::now(),
|
||||
precision: TimestampPrecision::Micros,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a [`Timestamp`] for the current date and time in UTC with
|
||||
/// nanosecond precision.
|
||||
pub fn timestamp_nanos(&self) -> Timestamp {
|
||||
Timestamp {
|
||||
time: SystemTime::now(),
|
||||
precision: TimestampPrecision::Nanos,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An [RFC3339] formatted timestamp.
|
||||
///
|
||||
/// The timestamp implements [`Display`] and can be written to a [`Formatter`].
|
||||
///
|
||||
/// [RFC3339]: https://www.ietf.org/rfc/rfc3339.txt
|
||||
/// [`Display`]: https://doc.rust-lang.org/stable/std/fmt/trait.Display.html
|
||||
/// [`Formatter`]: struct.Formatter.html
|
||||
pub struct Timestamp {
|
||||
time: SystemTime,
|
||||
precision: TimestampPrecision,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Timestamp {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// A `Debug` wrapper for `Timestamp` that uses the `Display` implementation.
|
||||
struct TimestampValue<'a>(&'a Timestamp);
|
||||
|
||||
impl<'a> fmt::Debug for TimestampValue<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
f.debug_tuple("Timestamp")
|
||||
.field(&TimestampValue(self))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Timestamp {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let formatter = match self.precision {
|
||||
TimestampPrecision::Seconds => format_rfc3339_seconds,
|
||||
TimestampPrecision::Millis => format_rfc3339_millis,
|
||||
TimestampPrecision::Micros => format_rfc3339_micros,
|
||||
TimestampPrecision::Nanos => format_rfc3339_nanos,
|
||||
};
|
||||
|
||||
formatter(self.time).fmt(f)
|
||||
}
|
||||
}
|
||||
11
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/humantime/mod.rs
vendored
Normal file
11
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/humantime/mod.rs
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
This internal module contains the timestamp implementation.
|
||||
|
||||
Its public API is available when the `humantime` crate is available.
|
||||
*/
|
||||
|
||||
#[cfg_attr(feature = "humantime", path = "extern_impl.rs")]
|
||||
#[cfg_attr(not(feature = "humantime"), path = "shim_impl.rs")]
|
||||
mod imp;
|
||||
|
||||
pub(in crate::fmt) use self::imp::*;
|
||||
5
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/humantime/shim_impl.rs
vendored
Normal file
5
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/humantime/shim_impl.rs
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Timestamps aren't available when we don't have a `humantime` dependency.
|
||||
*/
|
||||
|
||||
pub(in crate::fmt) mod glob {}
|
||||
652
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/mod.rs
vendored
Normal file
652
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/mod.rs
vendored
Normal file
@@ -0,0 +1,652 @@
|
||||
//! Formatting for log records.
|
||||
//!
|
||||
//! This module contains a [`Formatter`] that can be used to format log records
|
||||
//! into without needing temporary allocations. Usually you won't need to worry
|
||||
//! about the contents of this module and can use the `Formatter` like an ordinary
|
||||
//! [`Write`].
|
||||
//!
|
||||
//! # Formatting log records
|
||||
//!
|
||||
//! The format used to print log records can be customised using the [`Builder::format`]
|
||||
//! method.
|
||||
//! Custom formats can apply different color and weight to printed values using
|
||||
//! [`Style`] builders.
|
||||
//!
|
||||
//! ```
|
||||
//! use std::io::Write;
|
||||
//!
|
||||
//! let mut builder = env_logger::Builder::new();
|
||||
//!
|
||||
//! builder.format(|buf, record| {
|
||||
//! writeln!(buf, "{}: {}",
|
||||
//! record.level(),
|
||||
//! record.args())
|
||||
//! });
|
||||
//! ```
|
||||
//!
|
||||
//! [`Formatter`]: struct.Formatter.html
|
||||
//! [`Style`]: struct.Style.html
|
||||
//! [`Builder::format`]: ../struct.Builder.html#method.format
|
||||
//! [`Write`]: https://doc.rust-lang.org/stable/std/io/trait.Write.html
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::Display;
|
||||
use std::io::prelude::*;
|
||||
use std::rc::Rc;
|
||||
use std::{fmt, io, mem};
|
||||
|
||||
use log::Record;
|
||||
|
||||
mod humantime;
|
||||
pub(crate) mod writer;
|
||||
|
||||
pub use self::humantime::glob::*;
|
||||
pub use self::writer::glob::*;
|
||||
|
||||
use self::writer::{Buffer, Writer};
|
||||
|
||||
pub(crate) mod glob {
|
||||
pub use super::{Target, TimestampPrecision, WriteStyle};
|
||||
}
|
||||
|
||||
/// Formatting precision of timestamps.
|
||||
///
|
||||
/// Seconds give precision of full seconds, milliseconds give thousands of a
|
||||
/// second (3 decimal digits), microseconds are millionth of a second (6 decimal
|
||||
/// digits) and nanoseconds are billionth of a second (9 decimal digits).
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum TimestampPrecision {
|
||||
/// Full second precision (0 decimal digits)
|
||||
Seconds,
|
||||
/// Millisecond precision (3 decimal digits)
|
||||
Millis,
|
||||
/// Microsecond precision (6 decimal digits)
|
||||
Micros,
|
||||
/// Nanosecond precision (9 decimal digits)
|
||||
Nanos,
|
||||
}
|
||||
|
||||
/// The default timestamp precision is seconds.
|
||||
impl Default for TimestampPrecision {
|
||||
fn default() -> Self {
|
||||
TimestampPrecision::Seconds
|
||||
}
|
||||
}
|
||||
|
||||
/// A formatter to write logs into.
|
||||
///
|
||||
/// `Formatter` implements the standard [`Write`] trait for writing log records.
|
||||
/// It also supports terminal colors, through the [`style`] method.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Use the [`writeln`] macro to format a log record.
|
||||
/// An instance of a `Formatter` is passed to an `env_logger` format as `buf`:
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Write;
|
||||
///
|
||||
/// let mut builder = env_logger::Builder::new();
|
||||
///
|
||||
/// builder.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args()));
|
||||
/// ```
|
||||
///
|
||||
/// [`Write`]: https://doc.rust-lang.org/stable/std/io/trait.Write.html
|
||||
/// [`writeln`]: https://doc.rust-lang.org/stable/std/macro.writeln.html
|
||||
/// [`style`]: #method.style
|
||||
pub struct Formatter {
|
||||
buf: Rc<RefCell<Buffer>>,
|
||||
write_style: WriteStyle,
|
||||
}
|
||||
|
||||
impl Formatter {
|
||||
pub(crate) fn new(writer: &Writer) -> Self {
|
||||
Formatter {
|
||||
buf: Rc::new(RefCell::new(writer.buffer())),
|
||||
write_style: writer.write_style(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn write_style(&self) -> WriteStyle {
|
||||
self.write_style
|
||||
}
|
||||
|
||||
pub(crate) fn print(&self, writer: &Writer) -> io::Result<()> {
|
||||
writer.print(&self.buf.borrow())
|
||||
}
|
||||
|
||||
pub(crate) fn clear(&mut self) {
|
||||
self.buf.borrow_mut().clear()
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for Formatter {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.buf.borrow_mut().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.buf.borrow_mut().flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Formatter {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Formatter").finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type FormatFn = Box<dyn Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send>;
|
||||
|
||||
pub(crate) struct Builder {
|
||||
pub format_timestamp: Option<TimestampPrecision>,
|
||||
pub format_module_path: bool,
|
||||
pub format_target: bool,
|
||||
pub format_level: bool,
|
||||
pub format_indent: Option<usize>,
|
||||
pub custom_format: Option<FormatFn>,
|
||||
pub format_suffix: &'static str,
|
||||
built: bool,
|
||||
}
|
||||
|
||||
impl Default for Builder {
|
||||
fn default() -> Self {
|
||||
Builder {
|
||||
format_timestamp: Some(Default::default()),
|
||||
format_module_path: false,
|
||||
format_target: true,
|
||||
format_level: true,
|
||||
format_indent: Some(4),
|
||||
custom_format: None,
|
||||
format_suffix: "\n",
|
||||
built: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
/// Convert the format into a callable function.
|
||||
///
|
||||
/// If the `custom_format` is `Some`, then any `default_format` switches are ignored.
|
||||
/// If the `custom_format` is `None`, then a default format is returned.
|
||||
/// Any `default_format` switches set to `false` won't be written by the format.
|
||||
pub fn build(&mut self) -> FormatFn {
|
||||
assert!(!self.built, "attempt to re-use consumed builder");
|
||||
|
||||
let built = mem::replace(
|
||||
self,
|
||||
Builder {
|
||||
built: true,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
if let Some(fmt) = built.custom_format {
|
||||
fmt
|
||||
} else {
|
||||
Box::new(move |buf, record| {
|
||||
let fmt = DefaultFormat {
|
||||
timestamp: built.format_timestamp,
|
||||
module_path: built.format_module_path,
|
||||
target: built.format_target,
|
||||
level: built.format_level,
|
||||
written_header_value: false,
|
||||
indent: built.format_indent,
|
||||
suffix: built.format_suffix,
|
||||
buf,
|
||||
};
|
||||
|
||||
fmt.write(record)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "termcolor")]
|
||||
type SubtleStyle = StyledValue<'static, &'static str>;
|
||||
#[cfg(not(feature = "termcolor"))]
|
||||
type SubtleStyle = &'static str;
|
||||
|
||||
/// The default format.
|
||||
///
|
||||
/// This format needs to work with any combination of crate features.
|
||||
struct DefaultFormat<'a> {
|
||||
timestamp: Option<TimestampPrecision>,
|
||||
module_path: bool,
|
||||
target: bool,
|
||||
level: bool,
|
||||
written_header_value: bool,
|
||||
indent: Option<usize>,
|
||||
buf: &'a mut Formatter,
|
||||
suffix: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> DefaultFormat<'a> {
|
||||
fn write(mut self, record: &Record) -> io::Result<()> {
|
||||
self.write_timestamp()?;
|
||||
self.write_level(record)?;
|
||||
self.write_module_path(record)?;
|
||||
self.write_target(record)?;
|
||||
self.finish_header()?;
|
||||
|
||||
self.write_args(record)
|
||||
}
|
||||
|
||||
fn subtle_style(&self, text: &'static str) -> SubtleStyle {
|
||||
#[cfg(feature = "termcolor")]
|
||||
{
|
||||
self.buf
|
||||
.style()
|
||||
.set_color(Color::Black)
|
||||
.set_intense(true)
|
||||
.clone()
|
||||
.into_value(text)
|
||||
}
|
||||
#[cfg(not(feature = "termcolor"))]
|
||||
{
|
||||
text
|
||||
}
|
||||
}
|
||||
|
||||
fn write_header_value<T>(&mut self, value: T) -> io::Result<()>
|
||||
where
|
||||
T: Display,
|
||||
{
|
||||
if !self.written_header_value {
|
||||
self.written_header_value = true;
|
||||
|
||||
let open_brace = self.subtle_style("[");
|
||||
write!(self.buf, "{}{}", open_brace, value)
|
||||
} else {
|
||||
write!(self.buf, " {}", value)
|
||||
}
|
||||
}
|
||||
|
||||
fn write_level(&mut self, record: &Record) -> io::Result<()> {
|
||||
if !self.level {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let level = {
|
||||
#[cfg(feature = "termcolor")]
|
||||
{
|
||||
self.buf.default_styled_level(record.level())
|
||||
}
|
||||
#[cfg(not(feature = "termcolor"))]
|
||||
{
|
||||
record.level()
|
||||
}
|
||||
};
|
||||
|
||||
self.write_header_value(format_args!("{:<5}", level))
|
||||
}
|
||||
|
||||
fn write_timestamp(&mut self) -> io::Result<()> {
|
||||
#[cfg(feature = "humantime")]
|
||||
{
|
||||
use self::TimestampPrecision::*;
|
||||
let ts = match self.timestamp {
|
||||
None => return Ok(()),
|
||||
Some(Seconds) => self.buf.timestamp_seconds(),
|
||||
Some(Millis) => self.buf.timestamp_millis(),
|
||||
Some(Micros) => self.buf.timestamp_micros(),
|
||||
Some(Nanos) => self.buf.timestamp_nanos(),
|
||||
};
|
||||
|
||||
self.write_header_value(ts)
|
||||
}
|
||||
#[cfg(not(feature = "humantime"))]
|
||||
{
|
||||
// Trick the compiler to think we have used self.timestamp
|
||||
// Workaround for "field is never used: `timestamp`" compiler nag.
|
||||
let _ = self.timestamp;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn write_module_path(&mut self, record: &Record) -> io::Result<()> {
|
||||
if !self.module_path {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(module_path) = record.module_path() {
|
||||
self.write_header_value(module_path)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn write_target(&mut self, record: &Record) -> io::Result<()> {
|
||||
if !self.target {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
match record.target() {
|
||||
"" => Ok(()),
|
||||
target => self.write_header_value(target),
|
||||
}
|
||||
}
|
||||
|
||||
fn finish_header(&mut self) -> io::Result<()> {
|
||||
if self.written_header_value {
|
||||
let close_brace = self.subtle_style("]");
|
||||
write!(self.buf, "{} ", close_brace)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn write_args(&mut self, record: &Record) -> io::Result<()> {
|
||||
match self.indent {
|
||||
// Fast path for no indentation
|
||||
None => write!(self.buf, "{}{}", record.args(), self.suffix),
|
||||
|
||||
Some(indent_count) => {
|
||||
// Create a wrapper around the buffer only if we have to actually indent the message
|
||||
|
||||
struct IndentWrapper<'a, 'b: 'a> {
|
||||
fmt: &'a mut DefaultFormat<'b>,
|
||||
indent_count: usize,
|
||||
}
|
||||
|
||||
impl<'a, 'b> Write for IndentWrapper<'a, 'b> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let mut first = true;
|
||||
for chunk in buf.split(|&x| x == b'\n') {
|
||||
if !first {
|
||||
write!(
|
||||
self.fmt.buf,
|
||||
"{}{:width$}",
|
||||
self.fmt.suffix,
|
||||
"",
|
||||
width = self.indent_count
|
||||
)?;
|
||||
}
|
||||
self.fmt.buf.write_all(chunk)?;
|
||||
first = false;
|
||||
}
|
||||
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.fmt.buf.flush()
|
||||
}
|
||||
}
|
||||
|
||||
// The explicit scope here is just to make older versions of Rust happy
|
||||
{
|
||||
let mut wrapper = IndentWrapper {
|
||||
fmt: self,
|
||||
indent_count,
|
||||
};
|
||||
write!(wrapper, "{}", record.args())?;
|
||||
}
|
||||
|
||||
write!(self.buf, "{}", self.suffix)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use log::{Level, Record};
|
||||
|
||||
fn write_record(record: Record, fmt: DefaultFormat) -> String {
|
||||
let buf = fmt.buf.buf.clone();
|
||||
|
||||
fmt.write(&record).expect("failed to write record");
|
||||
|
||||
let buf = buf.borrow();
|
||||
String::from_utf8(buf.bytes().to_vec()).expect("failed to read record")
|
||||
}
|
||||
|
||||
fn write_target(target: &str, fmt: DefaultFormat) -> String {
|
||||
write_record(
|
||||
Record::builder()
|
||||
.args(format_args!("log\nmessage"))
|
||||
.level(Level::Info)
|
||||
.file(Some("test.rs"))
|
||||
.line(Some(144))
|
||||
.module_path(Some("test::path"))
|
||||
.target(target)
|
||||
.build(),
|
||||
fmt,
|
||||
)
|
||||
}
|
||||
|
||||
fn write(fmt: DefaultFormat) -> String {
|
||||
write_target("", fmt)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_with_header() {
|
||||
let writer = writer::Builder::new()
|
||||
.write_style(WriteStyle::Never)
|
||||
.build();
|
||||
|
||||
let mut f = Formatter::new(&writer);
|
||||
|
||||
let written = write(DefaultFormat {
|
||||
timestamp: None,
|
||||
module_path: true,
|
||||
target: false,
|
||||
level: true,
|
||||
written_header_value: false,
|
||||
indent: None,
|
||||
suffix: "\n",
|
||||
buf: &mut f,
|
||||
});
|
||||
|
||||
assert_eq!("[INFO test::path] log\nmessage\n", written);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_no_header() {
|
||||
let writer = writer::Builder::new()
|
||||
.write_style(WriteStyle::Never)
|
||||
.build();
|
||||
|
||||
let mut f = Formatter::new(&writer);
|
||||
|
||||
let written = write(DefaultFormat {
|
||||
timestamp: None,
|
||||
module_path: false,
|
||||
target: false,
|
||||
level: false,
|
||||
written_header_value: false,
|
||||
indent: None,
|
||||
suffix: "\n",
|
||||
buf: &mut f,
|
||||
});
|
||||
|
||||
assert_eq!("log\nmessage\n", written);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_indent_spaces() {
|
||||
let writer = writer::Builder::new()
|
||||
.write_style(WriteStyle::Never)
|
||||
.build();
|
||||
|
||||
let mut f = Formatter::new(&writer);
|
||||
|
||||
let written = write(DefaultFormat {
|
||||
timestamp: None,
|
||||
module_path: true,
|
||||
target: false,
|
||||
level: true,
|
||||
written_header_value: false,
|
||||
indent: Some(4),
|
||||
suffix: "\n",
|
||||
buf: &mut f,
|
||||
});
|
||||
|
||||
assert_eq!("[INFO test::path] log\n message\n", written);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_indent_zero_spaces() {
|
||||
let writer = writer::Builder::new()
|
||||
.write_style(WriteStyle::Never)
|
||||
.build();
|
||||
|
||||
let mut f = Formatter::new(&writer);
|
||||
|
||||
let written = write(DefaultFormat {
|
||||
timestamp: None,
|
||||
module_path: true,
|
||||
target: false,
|
||||
level: true,
|
||||
written_header_value: false,
|
||||
indent: Some(0),
|
||||
suffix: "\n",
|
||||
buf: &mut f,
|
||||
});
|
||||
|
||||
assert_eq!("[INFO test::path] log\nmessage\n", written);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_indent_spaces_no_header() {
|
||||
let writer = writer::Builder::new()
|
||||
.write_style(WriteStyle::Never)
|
||||
.build();
|
||||
|
||||
let mut f = Formatter::new(&writer);
|
||||
|
||||
let written = write(DefaultFormat {
|
||||
timestamp: None,
|
||||
module_path: false,
|
||||
target: false,
|
||||
level: false,
|
||||
written_header_value: false,
|
||||
indent: Some(4),
|
||||
suffix: "\n",
|
||||
buf: &mut f,
|
||||
});
|
||||
|
||||
assert_eq!("log\n message\n", written);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_suffix() {
|
||||
let writer = writer::Builder::new()
|
||||
.write_style(WriteStyle::Never)
|
||||
.build();
|
||||
|
||||
let mut f = Formatter::new(&writer);
|
||||
|
||||
let written = write(DefaultFormat {
|
||||
timestamp: None,
|
||||
module_path: false,
|
||||
target: false,
|
||||
level: false,
|
||||
written_header_value: false,
|
||||
indent: None,
|
||||
suffix: "\n\n",
|
||||
buf: &mut f,
|
||||
});
|
||||
|
||||
assert_eq!("log\nmessage\n\n", written);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_suffix_with_indent() {
|
||||
let writer = writer::Builder::new()
|
||||
.write_style(WriteStyle::Never)
|
||||
.build();
|
||||
|
||||
let mut f = Formatter::new(&writer);
|
||||
|
||||
let written = write(DefaultFormat {
|
||||
timestamp: None,
|
||||
module_path: false,
|
||||
target: false,
|
||||
level: false,
|
||||
written_header_value: false,
|
||||
indent: Some(4),
|
||||
suffix: "\n\n",
|
||||
buf: &mut f,
|
||||
});
|
||||
|
||||
assert_eq!("log\n\n message\n\n", written);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_target() {
|
||||
let writer = writer::Builder::new()
|
||||
.write_style(WriteStyle::Never)
|
||||
.build();
|
||||
|
||||
let mut f = Formatter::new(&writer);
|
||||
|
||||
let written = write_target(
|
||||
"target",
|
||||
DefaultFormat {
|
||||
timestamp: None,
|
||||
module_path: true,
|
||||
target: true,
|
||||
level: true,
|
||||
written_header_value: false,
|
||||
indent: None,
|
||||
suffix: "\n",
|
||||
buf: &mut f,
|
||||
},
|
||||
);
|
||||
|
||||
assert_eq!("[INFO test::path target] log\nmessage\n", written);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_empty_target() {
|
||||
let writer = writer::Builder::new()
|
||||
.write_style(WriteStyle::Never)
|
||||
.build();
|
||||
|
||||
let mut f = Formatter::new(&writer);
|
||||
|
||||
let written = write(DefaultFormat {
|
||||
timestamp: None,
|
||||
module_path: true,
|
||||
target: true,
|
||||
level: true,
|
||||
written_header_value: false,
|
||||
indent: None,
|
||||
suffix: "\n",
|
||||
buf: &mut f,
|
||||
});
|
||||
|
||||
assert_eq!("[INFO test::path] log\nmessage\n", written);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_no_target() {
|
||||
let writer = writer::Builder::new()
|
||||
.write_style(WriteStyle::Never)
|
||||
.build();
|
||||
|
||||
let mut f = Formatter::new(&writer);
|
||||
|
||||
let written = write_target(
|
||||
"target",
|
||||
DefaultFormat {
|
||||
timestamp: None,
|
||||
module_path: true,
|
||||
target: false,
|
||||
level: true,
|
||||
written_header_value: false,
|
||||
indent: None,
|
||||
suffix: "\n",
|
||||
buf: &mut f,
|
||||
},
|
||||
);
|
||||
|
||||
assert_eq!("[INFO test::path] log\nmessage\n", written);
|
||||
}
|
||||
}
|
||||
32
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/writer/atty.rs
vendored
Normal file
32
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/writer/atty.rs
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
This internal module contains the terminal detection implementation.
|
||||
|
||||
If the `atty` crate is available then we use it to detect whether we're
|
||||
attached to a particular TTY. If the `atty` crate is not available we
|
||||
assume we're not attached to anything. This effectively prevents styles
|
||||
from being printed.
|
||||
*/
|
||||
|
||||
#[cfg(feature = "atty")]
|
||||
mod imp {
|
||||
pub(in crate::fmt) fn is_stdout() -> bool {
|
||||
atty::is(atty::Stream::Stdout)
|
||||
}
|
||||
|
||||
pub(in crate::fmt) fn is_stderr() -> bool {
|
||||
atty::is(atty::Stream::Stderr)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "atty"))]
|
||||
mod imp {
|
||||
pub(in crate::fmt) fn is_stdout() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub(in crate::fmt) fn is_stderr() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate::fmt) use self::imp::*;
|
||||
252
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/writer/mod.rs
vendored
Normal file
252
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/writer/mod.rs
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
mod atty;
|
||||
mod termcolor;
|
||||
|
||||
use self::atty::{is_stderr, is_stdout};
|
||||
use self::termcolor::BufferWriter;
|
||||
use std::{fmt, io, mem, sync::Mutex};
|
||||
|
||||
pub(super) mod glob {
|
||||
pub use super::termcolor::glob::*;
|
||||
pub use super::*;
|
||||
}
|
||||
|
||||
pub(super) use self::termcolor::Buffer;
|
||||
|
||||
/// Log target, either `stdout`, `stderr` or a custom pipe.
|
||||
#[non_exhaustive]
|
||||
pub enum Target {
|
||||
/// Logs will be sent to standard output.
|
||||
Stdout,
|
||||
/// Logs will be sent to standard error.
|
||||
Stderr,
|
||||
/// Logs will be sent to a custom pipe.
|
||||
Pipe(Box<dyn io::Write + Send + 'static>),
|
||||
}
|
||||
|
||||
impl Default for Target {
|
||||
fn default() -> Self {
|
||||
Target::Stderr
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Target {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Self::Stdout => "stdout",
|
||||
Self::Stderr => "stderr",
|
||||
Self::Pipe(_) => "pipe",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Log target, either `stdout`, `stderr` or a custom pipe.
|
||||
///
|
||||
/// Same as `Target`, except the pipe is wrapped in a mutex for interior mutability.
|
||||
pub(super) enum WritableTarget {
|
||||
/// Logs will be sent to standard output.
|
||||
Stdout,
|
||||
/// Logs will be sent to standard error.
|
||||
Stderr,
|
||||
/// Logs will be sent to a custom pipe.
|
||||
Pipe(Box<Mutex<dyn io::Write + Send + 'static>>),
|
||||
}
|
||||
|
||||
impl From<Target> for WritableTarget {
|
||||
fn from(target: Target) -> Self {
|
||||
match target {
|
||||
Target::Stdout => Self::Stdout,
|
||||
Target::Stderr => Self::Stderr,
|
||||
Target::Pipe(pipe) => Self::Pipe(Box::new(Mutex::new(pipe))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for WritableTarget {
|
||||
fn default() -> Self {
|
||||
Self::from(Target::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for WritableTarget {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Self::Stdout => "stdout",
|
||||
Self::Stderr => "stderr",
|
||||
Self::Pipe(_) => "pipe",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
/// Whether or not to print styles to the target.
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
pub enum WriteStyle {
|
||||
/// Try to print styles, but don't force the issue.
|
||||
Auto,
|
||||
/// Try very hard to print styles.
|
||||
Always,
|
||||
/// Never print styles.
|
||||
Never,
|
||||
}
|
||||
|
||||
impl Default for WriteStyle {
|
||||
fn default() -> Self {
|
||||
WriteStyle::Auto
|
||||
}
|
||||
}
|
||||
|
||||
/// A terminal target with color awareness.
|
||||
pub(crate) struct Writer {
|
||||
inner: BufferWriter,
|
||||
write_style: WriteStyle,
|
||||
}
|
||||
|
||||
impl Writer {
|
||||
pub fn write_style(&self) -> WriteStyle {
|
||||
self.write_style
|
||||
}
|
||||
|
||||
pub(super) fn buffer(&self) -> Buffer {
|
||||
self.inner.buffer()
|
||||
}
|
||||
|
||||
pub(super) fn print(&self, buf: &Buffer) -> io::Result<()> {
|
||||
self.inner.print(buf)
|
||||
}
|
||||
}
|
||||
|
||||
/// A builder for a terminal writer.
|
||||
///
|
||||
/// The target and style choice can be configured before building.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Builder {
|
||||
target: WritableTarget,
|
||||
write_style: WriteStyle,
|
||||
is_test: bool,
|
||||
built: bool,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
/// Initialize the writer builder with defaults.
|
||||
pub(crate) fn new() -> Self {
|
||||
Builder {
|
||||
target: Default::default(),
|
||||
write_style: Default::default(),
|
||||
is_test: false,
|
||||
built: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the target to write to.
|
||||
pub(crate) fn target(&mut self, target: Target) -> &mut Self {
|
||||
self.target = target.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Parses a style choice string.
|
||||
///
|
||||
/// See the [Disabling colors] section for more details.
|
||||
///
|
||||
/// [Disabling colors]: ../index.html#disabling-colors
|
||||
pub(crate) fn parse_write_style(&mut self, write_style: &str) -> &mut Self {
|
||||
self.write_style(parse_write_style(write_style))
|
||||
}
|
||||
|
||||
/// Whether or not to print style characters when writing.
|
||||
pub(crate) fn write_style(&mut self, write_style: WriteStyle) -> &mut Self {
|
||||
self.write_style = write_style;
|
||||
self
|
||||
}
|
||||
|
||||
/// Whether or not to capture logs for `cargo test`.
|
||||
pub(crate) fn is_test(&mut self, is_test: bool) -> &mut Self {
|
||||
self.is_test = is_test;
|
||||
self
|
||||
}
|
||||
|
||||
/// Build a terminal writer.
|
||||
pub(crate) fn build(&mut self) -> Writer {
|
||||
assert!(!self.built, "attempt to re-use consumed builder");
|
||||
self.built = true;
|
||||
|
||||
let color_choice = match self.write_style {
|
||||
WriteStyle::Auto => {
|
||||
if match &self.target {
|
||||
WritableTarget::Stderr => is_stderr(),
|
||||
WritableTarget::Stdout => is_stdout(),
|
||||
WritableTarget::Pipe(_) => false,
|
||||
} {
|
||||
WriteStyle::Auto
|
||||
} else {
|
||||
WriteStyle::Never
|
||||
}
|
||||
}
|
||||
color_choice => color_choice,
|
||||
};
|
||||
|
||||
let writer = match mem::take(&mut self.target) {
|
||||
WritableTarget::Stderr => BufferWriter::stderr(self.is_test, color_choice),
|
||||
WritableTarget::Stdout => BufferWriter::stdout(self.is_test, color_choice),
|
||||
WritableTarget::Pipe(pipe) => BufferWriter::pipe(color_choice, pipe),
|
||||
};
|
||||
|
||||
Writer {
|
||||
inner: writer,
|
||||
write_style: self.write_style,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Builder {
|
||||
fn default() -> Self {
|
||||
Builder::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Writer {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Writer").finish()
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_write_style(spec: &str) -> WriteStyle {
|
||||
match spec {
|
||||
"auto" => WriteStyle::Auto,
|
||||
"always" => WriteStyle::Always,
|
||||
"never" => WriteStyle::Never,
|
||||
_ => Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse_write_style_valid() {
|
||||
let inputs = vec![
|
||||
("auto", WriteStyle::Auto),
|
||||
("always", WriteStyle::Always),
|
||||
("never", WriteStyle::Never),
|
||||
];
|
||||
|
||||
for (input, expected) in inputs {
|
||||
assert_eq!(expected, parse_write_style(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_write_style_invalid() {
|
||||
let inputs = vec!["", "true", "false", "NEVER!!"];
|
||||
|
||||
for input in inputs {
|
||||
assert_eq!(WriteStyle::Auto, parse_write_style(input));
|
||||
}
|
||||
}
|
||||
}
|
||||
532
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/writer/termcolor/extern_impl.rs
vendored
Normal file
532
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/writer/termcolor/extern_impl.rs
vendored
Normal file
@@ -0,0 +1,532 @@
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
use std::io::{self, Write};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use log::Level;
|
||||
use termcolor::{self, ColorChoice, ColorSpec, WriteColor};
|
||||
|
||||
use crate::fmt::{Formatter, WritableTarget, WriteStyle};
|
||||
|
||||
pub(in crate::fmt::writer) mod glob {
|
||||
pub use super::*;
|
||||
}
|
||||
|
||||
impl Formatter {
|
||||
/// Begin a new [`Style`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Create a bold, red colored style and use it to print the log level:
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Write;
|
||||
/// use env_logger::fmt::Color;
|
||||
///
|
||||
/// let mut builder = env_logger::Builder::new();
|
||||
///
|
||||
/// builder.format(|buf, record| {
|
||||
/// let mut level_style = buf.style();
|
||||
///
|
||||
/// level_style.set_color(Color::Red).set_bold(true);
|
||||
///
|
||||
/// writeln!(buf, "{}: {}",
|
||||
/// level_style.value(record.level()),
|
||||
/// record.args())
|
||||
/// });
|
||||
/// ```
|
||||
///
|
||||
/// [`Style`]: struct.Style.html
|
||||
pub fn style(&self) -> Style {
|
||||
Style {
|
||||
buf: self.buf.clone(),
|
||||
spec: ColorSpec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the default [`Style`] for the given level.
|
||||
///
|
||||
/// The style can be used to print other values besides the level.
|
||||
pub fn default_level_style(&self, level: Level) -> Style {
|
||||
let mut level_style = self.style();
|
||||
match level {
|
||||
Level::Trace => level_style.set_color(Color::Cyan),
|
||||
Level::Debug => level_style.set_color(Color::Blue),
|
||||
Level::Info => level_style.set_color(Color::Green),
|
||||
Level::Warn => level_style.set_color(Color::Yellow),
|
||||
Level::Error => level_style.set_color(Color::Red).set_bold(true),
|
||||
};
|
||||
level_style
|
||||
}
|
||||
|
||||
/// Get a printable [`Style`] for the given level.
|
||||
///
|
||||
/// The style can only be used to print the level.
|
||||
pub fn default_styled_level(&self, level: Level) -> StyledValue<'static, Level> {
|
||||
self.default_level_style(level).into_value(level)
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate::fmt::writer) struct BufferWriter {
|
||||
inner: termcolor::BufferWriter,
|
||||
uncolored_target: Option<WritableTarget>,
|
||||
}
|
||||
|
||||
pub(in crate::fmt) struct Buffer {
|
||||
inner: termcolor::Buffer,
|
||||
has_uncolored_target: bool,
|
||||
}
|
||||
|
||||
impl BufferWriter {
|
||||
pub(in crate::fmt::writer) fn stderr(is_test: bool, write_style: WriteStyle) -> Self {
|
||||
BufferWriter {
|
||||
inner: termcolor::BufferWriter::stderr(write_style.into_color_choice()),
|
||||
uncolored_target: if is_test {
|
||||
Some(WritableTarget::Stderr)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate::fmt::writer) fn stdout(is_test: bool, write_style: WriteStyle) -> Self {
|
||||
BufferWriter {
|
||||
inner: termcolor::BufferWriter::stdout(write_style.into_color_choice()),
|
||||
uncolored_target: if is_test {
|
||||
Some(WritableTarget::Stdout)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate::fmt::writer) fn pipe(
|
||||
write_style: WriteStyle,
|
||||
pipe: Box<Mutex<dyn io::Write + Send + 'static>>,
|
||||
) -> Self {
|
||||
BufferWriter {
|
||||
// The inner Buffer is never printed from, but it is still needed to handle coloring and other formating
|
||||
inner: termcolor::BufferWriter::stderr(write_style.into_color_choice()),
|
||||
uncolored_target: Some(WritableTarget::Pipe(pipe)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate::fmt::writer) fn buffer(&self) -> Buffer {
|
||||
Buffer {
|
||||
inner: self.inner.buffer(),
|
||||
has_uncolored_target: self.uncolored_target.is_some(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate::fmt::writer) fn print(&self, buf: &Buffer) -> io::Result<()> {
|
||||
if let Some(target) = &self.uncolored_target {
|
||||
// This impl uses the `eprint` and `print` macros
|
||||
// instead of `termcolor`'s buffer.
|
||||
// This is so their output can be captured by `cargo test`
|
||||
let log = String::from_utf8_lossy(buf.bytes());
|
||||
|
||||
match target {
|
||||
WritableTarget::Stderr => eprint!("{}", log),
|
||||
WritableTarget::Stdout => print!("{}", log),
|
||||
WritableTarget::Pipe(pipe) => write!(pipe.lock().unwrap(), "{}", log)?,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
self.inner.print(&buf.inner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
pub(in crate::fmt) fn clear(&mut self) {
|
||||
self.inner.clear()
|
||||
}
|
||||
|
||||
pub(in crate::fmt) fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.write(buf)
|
||||
}
|
||||
|
||||
pub(in crate::fmt) fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.flush()
|
||||
}
|
||||
|
||||
pub(in crate::fmt) fn bytes(&self) -> &[u8] {
|
||||
self.inner.as_slice()
|
||||
}
|
||||
|
||||
fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
|
||||
// Ignore styles for test captured logs because they can't be printed
|
||||
if !self.has_uncolored_target {
|
||||
self.inner.set_color(spec)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn reset(&mut self) -> io::Result<()> {
|
||||
// Ignore styles for test captured logs because they can't be printed
|
||||
if !self.has_uncolored_target {
|
||||
self.inner.reset()
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteStyle {
|
||||
fn into_color_choice(self) -> ColorChoice {
|
||||
match self {
|
||||
WriteStyle::Always => ColorChoice::Always,
|
||||
WriteStyle::Auto => ColorChoice::Auto,
|
||||
WriteStyle::Never => ColorChoice::Never,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A set of styles to apply to the terminal output.
|
||||
///
|
||||
/// Call [`Formatter::style`] to get a `Style` and use the builder methods to
|
||||
/// set styling properties, like [color] and [weight].
|
||||
/// To print a value using the style, wrap it in a call to [`value`] when the log
|
||||
/// record is formatted.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Create a bold, red colored style and use it to print the log level:
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Write;
|
||||
/// use env_logger::fmt::Color;
|
||||
///
|
||||
/// let mut builder = env_logger::Builder::new();
|
||||
///
|
||||
/// builder.format(|buf, record| {
|
||||
/// let mut level_style = buf.style();
|
||||
///
|
||||
/// level_style.set_color(Color::Red).set_bold(true);
|
||||
///
|
||||
/// writeln!(buf, "{}: {}",
|
||||
/// level_style.value(record.level()),
|
||||
/// record.args())
|
||||
/// });
|
||||
/// ```
|
||||
///
|
||||
/// Styles can be re-used to output multiple values:
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Write;
|
||||
/// use env_logger::fmt::Color;
|
||||
///
|
||||
/// let mut builder = env_logger::Builder::new();
|
||||
///
|
||||
/// builder.format(|buf, record| {
|
||||
/// let mut bold = buf.style();
|
||||
///
|
||||
/// bold.set_bold(true);
|
||||
///
|
||||
/// writeln!(buf, "{}: {} {}",
|
||||
/// bold.value(record.level()),
|
||||
/// bold.value("some bold text"),
|
||||
/// record.args())
|
||||
/// });
|
||||
/// ```
|
||||
///
|
||||
/// [`Formatter::style`]: struct.Formatter.html#method.style
|
||||
/// [color]: #method.set_color
|
||||
/// [weight]: #method.set_bold
|
||||
/// [`value`]: #method.value
|
||||
#[derive(Clone)]
|
||||
pub struct Style {
|
||||
buf: Rc<RefCell<Buffer>>,
|
||||
spec: ColorSpec,
|
||||
}
|
||||
|
||||
/// A value that can be printed using the given styles.
|
||||
///
|
||||
/// It is the result of calling [`Style::value`].
|
||||
///
|
||||
/// [`Style::value`]: struct.Style.html#method.value
|
||||
pub struct StyledValue<'a, T> {
|
||||
style: Cow<'a, Style>,
|
||||
value: T,
|
||||
}
|
||||
|
||||
impl Style {
|
||||
/// Set the text color.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Create a style with red text:
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Write;
|
||||
/// use env_logger::fmt::Color;
|
||||
///
|
||||
/// let mut builder = env_logger::Builder::new();
|
||||
///
|
||||
/// builder.format(|buf, record| {
|
||||
/// let mut style = buf.style();
|
||||
///
|
||||
/// style.set_color(Color::Red);
|
||||
///
|
||||
/// writeln!(buf, "{}", style.value(record.args()))
|
||||
/// });
|
||||
/// ```
|
||||
pub fn set_color(&mut self, color: Color) -> &mut Style {
|
||||
self.spec.set_fg(Some(color.into_termcolor()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the text weight.
|
||||
///
|
||||
/// If `yes` is true then text will be written in bold.
|
||||
/// If `yes` is false then text will be written in the default weight.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Create a style with bold text:
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Write;
|
||||
///
|
||||
/// let mut builder = env_logger::Builder::new();
|
||||
///
|
||||
/// builder.format(|buf, record| {
|
||||
/// let mut style = buf.style();
|
||||
///
|
||||
/// style.set_bold(true);
|
||||
///
|
||||
/// writeln!(buf, "{}", style.value(record.args()))
|
||||
/// });
|
||||
/// ```
|
||||
pub fn set_bold(&mut self, yes: bool) -> &mut Style {
|
||||
self.spec.set_bold(yes);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the text intensity.
|
||||
///
|
||||
/// If `yes` is true then text will be written in a brighter color.
|
||||
/// If `yes` is false then text will be written in the default color.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Create a style with intense text:
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Write;
|
||||
///
|
||||
/// let mut builder = env_logger::Builder::new();
|
||||
///
|
||||
/// builder.format(|buf, record| {
|
||||
/// let mut style = buf.style();
|
||||
///
|
||||
/// style.set_intense(true);
|
||||
///
|
||||
/// writeln!(buf, "{}", style.value(record.args()))
|
||||
/// });
|
||||
/// ```
|
||||
pub fn set_intense(&mut self, yes: bool) -> &mut Style {
|
||||
self.spec.set_intense(yes);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set whether the text is dimmed.
|
||||
///
|
||||
/// If `yes` is true then text will be written in a dimmer color.
|
||||
/// If `yes` is false then text will be written in the default color.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Create a style with dimmed text:
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Write;
|
||||
///
|
||||
/// let mut builder = env_logger::Builder::new();
|
||||
///
|
||||
/// builder.format(|buf, record| {
|
||||
/// let mut style = buf.style();
|
||||
///
|
||||
/// style.set_dimmed(true);
|
||||
///
|
||||
/// writeln!(buf, "{}", style.value(record.args()))
|
||||
/// });
|
||||
/// ```
|
||||
pub fn set_dimmed(&mut self, yes: bool) -> &mut Style {
|
||||
self.spec.set_dimmed(yes);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the background color.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Create a style with a yellow background:
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Write;
|
||||
/// use env_logger::fmt::Color;
|
||||
///
|
||||
/// let mut builder = env_logger::Builder::new();
|
||||
///
|
||||
/// builder.format(|buf, record| {
|
||||
/// let mut style = buf.style();
|
||||
///
|
||||
/// style.set_bg(Color::Yellow);
|
||||
///
|
||||
/// writeln!(buf, "{}", style.value(record.args()))
|
||||
/// });
|
||||
/// ```
|
||||
pub fn set_bg(&mut self, color: Color) -> &mut Style {
|
||||
self.spec.set_bg(Some(color.into_termcolor()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Wrap a value in the style.
|
||||
///
|
||||
/// The same `Style` can be used to print multiple different values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Create a bold, red colored style and use it to print the log level:
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Write;
|
||||
/// use env_logger::fmt::Color;
|
||||
///
|
||||
/// let mut builder = env_logger::Builder::new();
|
||||
///
|
||||
/// builder.format(|buf, record| {
|
||||
/// let mut style = buf.style();
|
||||
///
|
||||
/// style.set_color(Color::Red).set_bold(true);
|
||||
///
|
||||
/// writeln!(buf, "{}: {}",
|
||||
/// style.value(record.level()),
|
||||
/// record.args())
|
||||
/// });
|
||||
/// ```
|
||||
pub fn value<T>(&self, value: T) -> StyledValue<T> {
|
||||
StyledValue {
|
||||
style: Cow::Borrowed(self),
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrap a value in the style by taking ownership of it.
|
||||
pub(crate) fn into_value<T>(self, value: T) -> StyledValue<'static, T> {
|
||||
StyledValue {
|
||||
style: Cow::Owned(self),
|
||||
value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> StyledValue<'a, T> {
|
||||
fn write_fmt<F>(&self, f: F) -> fmt::Result
|
||||
where
|
||||
F: FnOnce() -> fmt::Result,
|
||||
{
|
||||
self.style
|
||||
.buf
|
||||
.borrow_mut()
|
||||
.set_color(&self.style.spec)
|
||||
.map_err(|_| fmt::Error)?;
|
||||
|
||||
// Always try to reset the terminal style, even if writing failed
|
||||
let write = f();
|
||||
let reset = self.style.buf.borrow_mut().reset().map_err(|_| fmt::Error);
|
||||
|
||||
write.and(reset)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Style {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Style").field("spec", &self.spec).finish()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_styled_value_fmt {
|
||||
($($fmt_trait:path),*) => {
|
||||
$(
|
||||
impl<'a, T: $fmt_trait> $fmt_trait for StyledValue<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result {
|
||||
self.write_fmt(|| T::fmt(&self.value, f))
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
impl_styled_value_fmt!(
|
||||
fmt::Debug,
|
||||
fmt::Display,
|
||||
fmt::Pointer,
|
||||
fmt::Octal,
|
||||
fmt::Binary,
|
||||
fmt::UpperHex,
|
||||
fmt::LowerHex,
|
||||
fmt::UpperExp,
|
||||
fmt::LowerExp
|
||||
);
|
||||
|
||||
// The `Color` type is copied from https://github.com/BurntSushi/termcolor
|
||||
|
||||
/// The set of available colors for the terminal foreground/background.
|
||||
///
|
||||
/// The `Ansi256` and `Rgb` colors will only output the correct codes when
|
||||
/// paired with the `Ansi` `WriteColor` implementation.
|
||||
///
|
||||
/// The `Ansi256` and `Rgb` color types are not supported when writing colors
|
||||
/// on Windows using the console. If they are used on Windows, then they are
|
||||
/// silently ignored and no colors will be emitted.
|
||||
///
|
||||
/// This set may expand over time.
|
||||
///
|
||||
/// This type has a `FromStr` impl that can parse colors from their human
|
||||
/// readable form. The format is as follows:
|
||||
///
|
||||
/// 1. Any of the explicitly listed colors in English. They are matched
|
||||
/// case insensitively.
|
||||
/// 2. A single 8-bit integer, in either decimal or hexadecimal format.
|
||||
/// 3. A triple of 8-bit integers separated by a comma, where each integer is
|
||||
/// in decimal or hexadecimal format.
|
||||
///
|
||||
/// Hexadecimal numbers are written with a `0x` prefix.
|
||||
#[allow(missing_docs)]
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Color {
|
||||
Black,
|
||||
Blue,
|
||||
Green,
|
||||
Red,
|
||||
Cyan,
|
||||
Magenta,
|
||||
Yellow,
|
||||
White,
|
||||
Ansi256(u8),
|
||||
Rgb(u8, u8, u8),
|
||||
}
|
||||
|
||||
impl Color {
|
||||
fn into_termcolor(self) -> termcolor::Color {
|
||||
match self {
|
||||
Color::Black => termcolor::Color::Black,
|
||||
Color::Blue => termcolor::Color::Blue,
|
||||
Color::Green => termcolor::Color::Green,
|
||||
Color::Red => termcolor::Color::Red,
|
||||
Color::Cyan => termcolor::Color::Cyan,
|
||||
Color::Magenta => termcolor::Color::Magenta,
|
||||
Color::Yellow => termcolor::Color::Yellow,
|
||||
Color::White => termcolor::Color::White,
|
||||
Color::Ansi256(value) => termcolor::Color::Ansi256(value),
|
||||
Color::Rgb(r, g, b) => termcolor::Color::Rgb(r, g, b),
|
||||
}
|
||||
}
|
||||
}
|
||||
12
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/writer/termcolor/mod.rs
vendored
Normal file
12
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/writer/termcolor/mod.rs
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
This internal module contains the style and terminal writing implementation.
|
||||
|
||||
Its public API is available when the `termcolor` crate is available.
|
||||
The terminal printing is shimmed when the `termcolor` crate is not available.
|
||||
*/
|
||||
|
||||
#[cfg_attr(feature = "termcolor", path = "extern_impl.rs")]
|
||||
#[cfg_attr(not(feature = "termcolor"), path = "shim_impl.rs")]
|
||||
mod imp;
|
||||
|
||||
pub(in crate::fmt) use self::imp::*;
|
||||
72
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/writer/termcolor/shim_impl.rs
vendored
Normal file
72
clamav/libclamav_rust/.cargo/vendor/env_logger/src/fmt/writer/termcolor/shim_impl.rs
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
use std::{io, sync::Mutex};
|
||||
|
||||
use crate::fmt::{WritableTarget, WriteStyle};
|
||||
|
||||
pub(in crate::fmt::writer) mod glob {}
|
||||
|
||||
pub(in crate::fmt::writer) struct BufferWriter {
|
||||
target: WritableTarget,
|
||||
}
|
||||
|
||||
pub(in crate::fmt) struct Buffer(Vec<u8>);
|
||||
|
||||
impl BufferWriter {
|
||||
pub(in crate::fmt::writer) fn stderr(_is_test: bool, _write_style: WriteStyle) -> Self {
|
||||
BufferWriter {
|
||||
target: WritableTarget::Stderr,
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate::fmt::writer) fn stdout(_is_test: bool, _write_style: WriteStyle) -> Self {
|
||||
BufferWriter {
|
||||
target: WritableTarget::Stdout,
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate::fmt::writer) fn pipe(
|
||||
_write_style: WriteStyle,
|
||||
pipe: Box<Mutex<dyn io::Write + Send + 'static>>,
|
||||
) -> Self {
|
||||
BufferWriter {
|
||||
target: WritableTarget::Pipe(pipe),
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate::fmt::writer) fn buffer(&self) -> Buffer {
|
||||
Buffer(Vec::new())
|
||||
}
|
||||
|
||||
pub(in crate::fmt::writer) fn print(&self, buf: &Buffer) -> io::Result<()> {
|
||||
// This impl uses the `eprint` and `print` macros
|
||||
// instead of using the streams directly.
|
||||
// This is so their output can be captured by `cargo test`.
|
||||
match &self.target {
|
||||
// Safety: If the target type is `Pipe`, `target_pipe` will always be non-empty.
|
||||
WritableTarget::Pipe(pipe) => pipe.lock().unwrap().write_all(&buf.0)?,
|
||||
WritableTarget::Stdout => print!("{}", String::from_utf8_lossy(&buf.0)),
|
||||
WritableTarget::Stderr => eprint!("{}", String::from_utf8_lossy(&buf.0)),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
pub(in crate::fmt) fn clear(&mut self) {
|
||||
self.0.clear();
|
||||
}
|
||||
|
||||
pub(in crate::fmt) fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.extend(buf);
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
pub(in crate::fmt) fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(in crate::fmt) fn bytes(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
1311
clamav/libclamav_rust/.cargo/vendor/env_logger/src/lib.rs
vendored
Normal file
1311
clamav/libclamav_rust/.cargo/vendor/env_logger/src/lib.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
40
clamav/libclamav_rust/.cargo/vendor/env_logger/tests/init-twice-retains-filter.rs
vendored
Normal file
40
clamav/libclamav_rust/.cargo/vendor/env_logger/tests/init-twice-retains-filter.rs
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
extern crate env_logger;
|
||||
extern crate log;
|
||||
|
||||
use std::env;
|
||||
use std::process;
|
||||
use std::str;
|
||||
|
||||
fn main() {
|
||||
if env::var("YOU_ARE_TESTING_NOW").is_ok() {
|
||||
// Init from the env (which should set the max level to `Debug`)
|
||||
env_logger::init();
|
||||
|
||||
assert_eq!(log::LevelFilter::Debug, log::max_level());
|
||||
|
||||
// Init again using a different max level
|
||||
// This shouldn't clobber the level that was previously set
|
||||
env_logger::Builder::new()
|
||||
.parse_filters("info")
|
||||
.try_init()
|
||||
.unwrap_err();
|
||||
|
||||
assert_eq!(log::LevelFilter::Debug, log::max_level());
|
||||
return;
|
||||
}
|
||||
|
||||
let exe = env::current_exe().unwrap();
|
||||
let out = process::Command::new(exe)
|
||||
.env("YOU_ARE_TESTING_NOW", "1")
|
||||
.env("RUST_LOG", "debug")
|
||||
.output()
|
||||
.unwrap_or_else(|e| panic!("Unable to start child process: {}", e));
|
||||
if out.status.success() {
|
||||
return;
|
||||
}
|
||||
|
||||
println!("test failed: {}", out.status);
|
||||
println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap());
|
||||
println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap());
|
||||
process::exit(1);
|
||||
}
|
||||
39
clamav/libclamav_rust/.cargo/vendor/env_logger/tests/log-in-log.rs
vendored
Normal file
39
clamav/libclamav_rust/.cargo/vendor/env_logger/tests/log-in-log.rs
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate env_logger;
|
||||
|
||||
use std::env;
|
||||
use std::fmt;
|
||||
use std::process;
|
||||
use std::str;
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl fmt::Display for Foo {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
info!("test");
|
||||
f.write_str("bar")
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
if env::var("YOU_ARE_TESTING_NOW").is_ok() {
|
||||
return info!("{}", Foo);
|
||||
}
|
||||
|
||||
let exe = env::current_exe().unwrap();
|
||||
let out = process::Command::new(exe)
|
||||
.env("YOU_ARE_TESTING_NOW", "1")
|
||||
.env("RUST_LOG", "debug")
|
||||
.output()
|
||||
.unwrap_or_else(|e| panic!("Unable to start child process: {}", e));
|
||||
if out.status.success() {
|
||||
return;
|
||||
}
|
||||
|
||||
println!("test failed: {}", out.status);
|
||||
println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap());
|
||||
println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap());
|
||||
process::exit(1);
|
||||
}
|
||||
66
clamav/libclamav_rust/.cargo/vendor/env_logger/tests/log_tls_dtors.rs
vendored
Normal file
66
clamav/libclamav_rust/.cargo/vendor/env_logger/tests/log_tls_dtors.rs
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate env_logger;
|
||||
|
||||
use std::env;
|
||||
use std::process;
|
||||
use std::str;
|
||||
use std::thread;
|
||||
|
||||
struct DropMe;
|
||||
|
||||
impl Drop for DropMe {
|
||||
fn drop(&mut self) {
|
||||
debug!("Dropping now");
|
||||
}
|
||||
}
|
||||
|
||||
fn run() {
|
||||
// Use multiple thread local values to increase the chance that our TLS
|
||||
// value will get destroyed after the FORMATTER key in the library
|
||||
thread_local! {
|
||||
static DROP_ME_0: DropMe = DropMe;
|
||||
static DROP_ME_1: DropMe = DropMe;
|
||||
static DROP_ME_2: DropMe = DropMe;
|
||||
static DROP_ME_3: DropMe = DropMe;
|
||||
static DROP_ME_4: DropMe = DropMe;
|
||||
static DROP_ME_5: DropMe = DropMe;
|
||||
static DROP_ME_6: DropMe = DropMe;
|
||||
static DROP_ME_7: DropMe = DropMe;
|
||||
static DROP_ME_8: DropMe = DropMe;
|
||||
static DROP_ME_9: DropMe = DropMe;
|
||||
}
|
||||
DROP_ME_0.with(|_| {});
|
||||
DROP_ME_1.with(|_| {});
|
||||
DROP_ME_2.with(|_| {});
|
||||
DROP_ME_3.with(|_| {});
|
||||
DROP_ME_4.with(|_| {});
|
||||
DROP_ME_5.with(|_| {});
|
||||
DROP_ME_6.with(|_| {});
|
||||
DROP_ME_7.with(|_| {});
|
||||
DROP_ME_8.with(|_| {});
|
||||
DROP_ME_9.with(|_| {});
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
if env::var("YOU_ARE_TESTING_NOW").is_ok() {
|
||||
// Run on a separate thread because TLS values on the main thread
|
||||
// won't have their destructors run if pthread is used.
|
||||
// https://doc.rust-lang.org/std/thread/struct.LocalKey.html#platform-specific-behavior
|
||||
thread::spawn(run).join().unwrap();
|
||||
} else {
|
||||
let exe = env::current_exe().unwrap();
|
||||
let out = process::Command::new(exe)
|
||||
.env("YOU_ARE_TESTING_NOW", "1")
|
||||
.env("RUST_LOG", "debug")
|
||||
.output()
|
||||
.unwrap_or_else(|e| panic!("Unable to start child process: {}", e));
|
||||
if !out.status.success() {
|
||||
println!("test failed: {}", out.status);
|
||||
println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap());
|
||||
println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap());
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
57
clamav/libclamav_rust/.cargo/vendor/env_logger/tests/regexp_filter.rs
vendored
Normal file
57
clamav/libclamav_rust/.cargo/vendor/env_logger/tests/regexp_filter.rs
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate env_logger;
|
||||
|
||||
use std::env;
|
||||
use std::process;
|
||||
use std::str;
|
||||
|
||||
fn main() {
|
||||
if env::var("LOG_REGEXP_TEST").ok() == Some(String::from("1")) {
|
||||
child_main();
|
||||
} else {
|
||||
parent_main()
|
||||
}
|
||||
}
|
||||
|
||||
fn child_main() {
|
||||
env_logger::init();
|
||||
info!("XYZ Message");
|
||||
}
|
||||
|
||||
fn run_child(rust_log: String) -> bool {
|
||||
let exe = env::current_exe().unwrap();
|
||||
let out = process::Command::new(exe)
|
||||
.env("LOG_REGEXP_TEST", "1")
|
||||
.env("RUST_LOG", rust_log)
|
||||
.output()
|
||||
.unwrap_or_else(|e| panic!("Unable to start child process: {}", e));
|
||||
str::from_utf8(out.stderr.as_ref())
|
||||
.unwrap()
|
||||
.contains("XYZ Message")
|
||||
}
|
||||
|
||||
fn assert_message_printed(rust_log: &str) {
|
||||
if !run_child(rust_log.to_string()) {
|
||||
panic!("RUST_LOG={} should allow the test log message", rust_log)
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_message_not_printed(rust_log: &str) {
|
||||
if run_child(rust_log.to_string()) {
|
||||
panic!(
|
||||
"RUST_LOG={} should not allow the test log message",
|
||||
rust_log
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn parent_main() {
|
||||
// test normal log severity levels
|
||||
assert_message_printed("info");
|
||||
assert_message_not_printed("warn");
|
||||
|
||||
// test of regular expression filters
|
||||
assert_message_printed("info/XYZ");
|
||||
assert_message_not_printed("info/XXX");
|
||||
}
|
||||
Reference in New Issue
Block a user