summaryrefslogtreecommitdiffstats
path: root/vendor/env_logger-0.7.1
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/env_logger-0.7.1')
-rw-r--r--vendor/env_logger-0.7.1/.cargo-checksum.json1
-rw-r--r--vendor/env_logger-0.7.1/CHANGELOG.md3
-rw-r--r--vendor/env_logger-0.7.1/Cargo.lock212
-rw-r--r--vendor/env_logger-0.7.1/Cargo.toml62
-rw-r--r--vendor/env_logger-0.7.1/LICENSE-APACHE201
-rw-r--r--vendor/env_logger-0.7.1/LICENSE-MIT25
-rw-r--r--vendor/env_logger-0.7.1/README.md150
-rw-r--r--vendor/env_logger-0.7.1/examples/custom_default_format.rs41
-rw-r--r--vendor/env_logger-0.7.1/examples/custom_format.rs53
-rw-r--r--vendor/env_logger-0.7.1/examples/custom_logger.rs60
-rw-r--r--vendor/env_logger-0.7.1/examples/default.rs38
-rw-r--r--vendor/env_logger-0.7.1/examples/direct_logger.rs37
-rw-r--r--vendor/env_logger-0.7.1/examples/filters_from_code.rs18
-rw-r--r--vendor/env_logger-0.7.1/src/filter/mod.rs616
-rw-r--r--vendor/env_logger-0.7.1/src/filter/regex.rs29
-rw-r--r--vendor/env_logger-0.7.1/src/filter/string.rs24
-rw-r--r--vendor/env_logger-0.7.1/src/fmt/humantime/extern_impl.rs118
-rw-r--r--vendor/env_logger-0.7.1/src/fmt/humantime/mod.rs11
-rw-r--r--vendor/env_logger-0.7.1/src/fmt/humantime/shim_impl.rs5
-rw-r--r--vendor/env_logger-0.7.1/src/fmt/mod.rs489
-rw-r--r--vendor/env_logger-0.7.1/src/fmt/writer/atty.rs34
-rw-r--r--vendor/env_logger-0.7.1/src/fmt/writer/mod.rs201
-rw-r--r--vendor/env_logger-0.7.1/src/fmt/writer/termcolor/extern_impl.rs486
-rw-r--r--vendor/env_logger-0.7.1/src/fmt/writer/termcolor/mod.rs12
-rw-r--r--vendor/env_logger-0.7.1/src/fmt/writer/termcolor/shim_impl.rs63
-rw-r--r--vendor/env_logger-0.7.1/src/lib.rs1177
-rw-r--r--vendor/env_logger-0.7.1/tests/init-twice-retains-filter.rs40
-rw-r--r--vendor/env_logger-0.7.1/tests/log-in-log.rs39
-rw-r--r--vendor/env_logger-0.7.1/tests/log_tls_dtors.rs66
-rw-r--r--vendor/env_logger-0.7.1/tests/regexp_filter.rs57
30 files changed, 4368 insertions, 0 deletions
diff --git a/vendor/env_logger-0.7.1/.cargo-checksum.json b/vendor/env_logger-0.7.1/.cargo-checksum.json
new file mode 100644
index 000000000..f7fcd9e6b
--- /dev/null
+++ b/vendor/env_logger-0.7.1/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"7c044d74477515ab39287a4caff27eb96daebaed8b9f9b6a1d1c081a7b42d4a7","Cargo.lock":"b1394b6c58241027832cc714a0754902d82aa1f6923ab478c318739462e565ca","Cargo.toml":"2961879155d753ba90ecd98c17875c82007a6973c95867e86bc1ec5bd4f5db41","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"0bf17650e07b88f1486f033643c1e82517caa69410e6faeaa352782d9231d63e","examples/custom_default_format.rs":"ae18cd0e765cf1f16568f9879925861d6f004481f955b58af5ed8fd04b0fca99","examples/custom_format.rs":"b0f41b7a3e6fe7582871281f4244c62c66b0d724bfc678907f67185a784e82b4","examples/custom_logger.rs":"6eeef506681a46925117e8f89395cdf4fea60a0d1f6a420e51768e790272dcde","examples/default.rs":"7ed1c6a8a8fe457a86676bd3a75c07d4ec7fb54147cf2825c9d299a5878a24cd","examples/direct_logger.rs":"ee20c25379c396e5e74e963290a4d8773a86f3fe10193f61fb1efd1c7271faf4","examples/filters_from_code.rs":"7f007b0dfa5a3964f839134824dc3684bf2f3c3d7b4c36c580cd029df5f9308b","src/filter/mod.rs":"5da7e51e7b77efdd4d2b5445e5d0264be2c897909d0f86eb553e16611307aed2","src/filter/regex.rs":"bdf875bac25e089e1e462f5dd01a88678067c24118ecd6268561c6a6af39747d","src/filter/string.rs":"fac54d51189fc0b5d2bff334b7a7e465177b431e3428299e345e1f90062d832e","src/fmt/humantime/extern_impl.rs":"f3087b29eedb8b4d5573621ad206e48a2eac72a77277be3b0e631d7dc9fb7a2e","src/fmt/humantime/mod.rs":"f4111c26cf2ffb85c1d639bd7674d55af7e1736e7e98c52f7be3070046a3253f","src/fmt/humantime/shim_impl.rs":"cce9a252abd5952fa109a72b1dfb85a593d237e22606b2b608a32c69184560e9","src/fmt/mod.rs":"4ab11971a73eb5fe9b40f0bca6dfc404321dd9e2ffcf87d911408e7183dc8362","src/fmt/writer/atty.rs":"69d9dd26c430000cd2d40f9c68b2e77cd492fec22921dd2c16864301252583e0","src/fmt/writer/mod.rs":"1e0feb4dee3ee86c4c24f49566673e99ec85765869105a07a2fc7436d7640cfe","src/fmt/writer/termcolor/extern_impl.rs":"89e9f2e66b914ddc960ad9a4355265a5db5d7be410b139cf2b54ca99207374a7","src/fmt/writer/termcolor/mod.rs":"a790f9391a50cd52be6823e3e55942de13a8d12e23d63765342ae9e8dd6d091c","src/fmt/writer/termcolor/shim_impl.rs":"d93786671d6a89fc2912f77f04b8cb0b82d67277d255d15ac31bfc1bc4464e30","src/lib.rs":"3cbc4f4d3fe51c43fc45a2f435c141f0de5b40b65ba0d2c7d16bb58c04d10898","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":"44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"} \ No newline at end of file
diff --git a/vendor/env_logger-0.7.1/CHANGELOG.md b/vendor/env_logger-0.7.1/CHANGELOG.md
new file mode 100644
index 000000000..f849eefff
--- /dev/null
+++ b/vendor/env_logger-0.7.1/CHANGELOG.md
@@ -0,0 +1,3 @@
+Changes to this crate are tracked via [GitHub Releases][releases].
+
+[releases]: https://github.com/sebasmagri/env_logger/releases
diff --git a/vendor/env_logger-0.7.1/Cargo.lock b/vendor/env_logger-0.7.1/Cargo.lock
new file mode 100644
index 000000000..bf04607aa
--- /dev/null
+++ b/vendor/env_logger-0.7.1/Cargo.lock
@@ -0,0 +1,212 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "aho-corasick"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cfg-if"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "env_logger"
+version = "0.7.1"
+dependencies = [
+ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "humantime"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libc"
+version = "0.2.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "log"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "memchr"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "quick-error"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "redox_syscall"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "redox_termios"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "termion"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thread_local"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "ucd-util"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "utf8-ranges"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "version_check"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "wincolor"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[metadata]
+"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
+"checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4"
+"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
+"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
+"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
+"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b"
+"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
+"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16"
+"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
+"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
+"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
+"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
+"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861"
+"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
+"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
+"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
+"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
+"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
+"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
+"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
+"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
+"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba"
diff --git a/vendor/env_logger-0.7.1/Cargo.toml b/vendor/env_logger-0.7.1/Cargo.toml
new file mode 100644
index 000000000..c34a1ee23
--- /dev/null
+++ b/vendor/env_logger-0.7.1/Cargo.toml
@@ -0,0 +1,62 @@
+# 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 believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "env_logger"
+version = "0.7.1"
+authors = ["The Rust Project Developers"]
+description = "A logging implementation for `log` which is configured via an environment\nvariable.\n"
+documentation = "https://docs.rs/env_logger"
+readme = "README.md"
+keywords = ["logging", "log", "logger"]
+categories = ["development-tools::debugging"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/sebasmagri/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 = "1.3"
+optional = true
+
+[dependencies.log]
+version = "0.4.8"
+features = ["std"]
+
+[dependencies.regex]
+version = "1.0.3"
+optional = true
+
+[dependencies.termcolor]
+version = "1.0.2"
+optional = true
+
+[features]
+default = ["termcolor", "atty", "humantime", "regex"]
diff --git a/vendor/env_logger-0.7.1/LICENSE-APACHE b/vendor/env_logger-0.7.1/LICENSE-APACHE
new file mode 100644
index 000000000..16fe87b06
--- /dev/null
+++ b/vendor/env_logger-0.7.1/LICENSE-APACHE
@@ -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.
diff --git a/vendor/env_logger-0.7.1/LICENSE-MIT b/vendor/env_logger-0.7.1/LICENSE-MIT
new file mode 100644
index 000000000..39d4bdb5a
--- /dev/null
+++ b/vendor/env_logger-0.7.1/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2014 The Rust Project Developers
+
+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.
diff --git a/vendor/env_logger-0.7.1/README.md b/vendor/env_logger-0.7.1/README.md
new file mode 100644
index 000000000..34e4194a8
--- /dev/null
+++ b/vendor/env_logger-0.7.1/README.md
@@ -0,0 +1,150 @@
+env_logger [![Build Status](https://travis-ci.org/sebasmagri/env_logger.svg?branch=master)](https://travis-ci.org/sebasmagri/env_logger) [![Maintenance](https://img.shields.io/badge/maintenance-actively%20maintained-brightgreen.svg)](https://github.com/sebasmagri/env_logger) [![crates.io](https://img.shields.io/crates/v/env_logger.svg)](https://crates.io/crates/env_logger) [![Documentation](https://img.shields.io/badge/docs-current-blue.svg)](https://docs.rs/env_logger)
+==========
+
+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://doc.rust-lang.org/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.7.1"
+```
+
+`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
+```
+
+`env_logger` can be configured in other ways besides an environment variable. See [the examples](https://github.com/sebasmagri/env_logger/tree/master/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.7.1"
+```
+
+```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.
diff --git a/vendor/env_logger-0.7.1/examples/custom_default_format.rs b/vendor/env_logger-0.7.1/examples/custom_default_format.rs
new file mode 100644
index 000000000..43979247c
--- /dev/null
+++ b/vendor/env_logger-0.7.1/examples/custom_default_format.rs
@@ -0,0 +1,41 @@
+/*!
+Disabling parts of the default format.
+
+Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`:
+
+```no_run,shell
+$ export MY_LOG_LEVEL='info'
+```
+
+Also try setting the `MY_LOG_STYLE` environment variable to `never` to disable colors
+or `auto` to enable them:
+
+```no_run,shell
+$ export MY_LOG_STYLE=never
+```
+
+If you want to control the logging output completely, see the `custom_logger` example.
+*/
+
+#[macro_use]
+extern crate log;
+
+use env_logger::{Builder, Env};
+
+fn init_logger() {
+ let env = Env::default()
+ .filter("MY_LOG_LEVEL")
+ .write_style("MY_LOG_STYLE");
+
+ let mut builder = Builder::from_env(env);
+
+ builder.format_level(false).format_timestamp_nanos();
+
+ builder.init();
+}
+
+fn main() {
+ init_logger();
+
+ info!("a log from `MyLogger`");
+}
diff --git a/vendor/env_logger-0.7.1/examples/custom_format.rs b/vendor/env_logger-0.7.1/examples/custom_format.rs
new file mode 100644
index 000000000..df5a8e5b9
--- /dev/null
+++ b/vendor/env_logger-0.7.1/examples/custom_format.rs
@@ -0,0 +1,53 @@
+/*!
+Changing the default logging format.
+
+Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`:
+
+```no_run,shell
+$ export MY_LOG_LEVEL='info'
+```
+
+Also try setting the `MY_LOG_STYLE` environment variable to `never` to disable colors
+or `auto` to enable them:
+
+```no_run,shell
+$ export MY_LOG_STYLE=never
+```
+
+If you want to control the logging output completely, see the `custom_logger` example.
+*/
+
+#[cfg(all(feature = "termcolor", feature = "humantime"))]
+fn main() {
+ use env_logger::{fmt, Builder, Env};
+ use std::io::Write;
+
+ fn init_logger() {
+ let env = Env::default()
+ .filter("MY_LOG_LEVEL")
+ .write_style("MY_LOG_STYLE");
+
+ Builder::from_env(env)
+ .format(|buf, record| {
+ let mut style = buf.style();
+ style.set_bg(fmt::Color::Yellow).set_bold(true);
+
+ let timestamp = buf.timestamp();
+
+ writeln!(
+ buf,
+ "My formatted log ({}): {}",
+ timestamp,
+ style.value(record.args())
+ )
+ })
+ .init();
+ }
+
+ init_logger();
+
+ log::info!("a log from `MyLogger`");
+}
+
+#[cfg(not(all(feature = "termcolor", feature = "humantime")))]
+fn main() {}
diff --git a/vendor/env_logger-0.7.1/examples/custom_logger.rs b/vendor/env_logger-0.7.1/examples/custom_logger.rs
new file mode 100644
index 000000000..85de45b2d
--- /dev/null
+++ b/vendor/env_logger-0.7.1/examples/custom_logger.rs
@@ -0,0 +1,60 @@
+/*!
+Using `env_logger` to drive a custom logger.
+
+Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`:
+
+```no_run,shell
+$ export MY_LOG_LEVEL='info'
+```
+
+If you only want to change the way logs are formatted, look at the `custom_format` example.
+*/
+
+#[macro_use]
+extern crate log;
+
+use env_logger::filter::Filter;
+use log::{Log, Metadata, Record, SetLoggerError};
+
+struct MyLogger {
+ inner: Filter,
+}
+
+impl MyLogger {
+ fn new() -> MyLogger {
+ use env_logger::filter::Builder;
+ let mut builder = Builder::from_env("MY_LOG_LEVEL");
+
+ MyLogger {
+ inner: builder.build(),
+ }
+ }
+
+ fn init() -> Result<(), SetLoggerError> {
+ let logger = Self::new();
+
+ log::set_max_level(logger.inner.filter());
+ log::set_boxed_logger(Box::new(logger))
+ }
+}
+
+impl Log for MyLogger {
+ fn enabled(&self, metadata: &Metadata) -> bool {
+ self.inner.enabled(metadata)
+ }
+
+ fn log(&self, record: &Record) {
+ // Check if the record is matched by the logger before logging
+ if self.inner.matches(record) {
+ println!("{} - {}", record.level(), record.args());
+ }
+ }
+
+ fn flush(&self) {}
+}
+
+fn main() {
+ MyLogger::init().unwrap();
+
+ info!("a log from `MyLogger`");
+}
diff --git a/vendor/env_logger-0.7.1/examples/default.rs b/vendor/env_logger-0.7.1/examples/default.rs
new file mode 100644
index 000000000..67bb03074
--- /dev/null
+++ b/vendor/env_logger-0.7.1/examples/default.rs
@@ -0,0 +1,38 @@
+/*!
+Using `env_logger`.
+
+Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`:
+
+```no_run,shell
+$ export MY_LOG_LEVEL='info'
+```
+
+Also try setting the `MY_LOG_STYLE` environment variable to `never` to disable colors
+or `auto` to enable them:
+
+```no_run,shell
+$ export MY_LOG_STYLE=never
+```
+*/
+
+#[macro_use]
+extern crate log;
+
+use env_logger::Env;
+
+fn main() {
+ // The `Env` lets us tweak what the environment
+ // variables to read are and what the default
+ // value is if they're missing
+ let env = Env::default()
+ .filter_or("MY_LOG_LEVEL", "trace")
+ .write_style_or("MY_LOG_STYLE", "always");
+
+ env_logger::init_from_env(env);
+
+ trace!("some trace log");
+ debug!("some debug log");
+ info!("some information log");
+ warn!("some warning log");
+ error!("some error log");
+}
diff --git a/vendor/env_logger-0.7.1/examples/direct_logger.rs b/vendor/env_logger-0.7.1/examples/direct_logger.rs
new file mode 100644
index 000000000..4ba023fae
--- /dev/null
+++ b/vendor/env_logger-0.7.1/examples/direct_logger.rs
@@ -0,0 +1,37 @@
+/*!
+Using `env_logger::Logger` and the `log::Log` trait directly.
+
+This example doesn't rely on environment variables, or having a static logger installed.
+*/
+
+fn record() -> log::Record<'static> {
+ let error_metadata = log::MetadataBuilder::new()
+ .target("myApp")
+ .level(log::Level::Error)
+ .build();
+
+ log::Record::builder()
+ .metadata(error_metadata)
+ .args(format_args!("Error!"))
+ .line(Some(433))
+ .file(Some("app.rs"))
+ .module_path(Some("server"))
+ .build()
+}
+
+fn main() {
+ use log::Log;
+
+ let stylish_logger = env_logger::Builder::new()
+ .filter(None, log::LevelFilter::Error)
+ .write_style(env_logger::WriteStyle::Always)
+ .build();
+
+ let unstylish_logger = env_logger::Builder::new()
+ .filter(None, log::LevelFilter::Error)
+ .write_style(env_logger::WriteStyle::Never)
+ .build();
+
+ stylish_logger.log(&record());
+ unstylish_logger.log(&record());
+}
diff --git a/vendor/env_logger-0.7.1/examples/filters_from_code.rs b/vendor/env_logger-0.7.1/examples/filters_from_code.rs
new file mode 100644
index 000000000..4137c9189
--- /dev/null
+++ b/vendor/env_logger-0.7.1/examples/filters_from_code.rs
@@ -0,0 +1,18 @@
+/*!
+Specify logging filters in code instead of using an environment variable.
+*/
+
+#[macro_use]
+extern crate log;
+
+fn main() {
+ env_logger::builder()
+ .filter_level(log::LevelFilter::Trace)
+ .init();
+
+ trace!("some trace log");
+ debug!("some debug log");
+ info!("some information log");
+ warn!("some warning log");
+ error!("some error log");
+}
diff --git a/vendor/env_logger-0.7.1/src/filter/mod.rs b/vendor/env_logger-0.7.1/src/filter/mod.rs
new file mode 100644
index 000000000..a994f4dc6
--- /dev/null
+++ b/vendor/env_logger-0.7.1/src/filter/mod.rs
@@ -0,0 +1,616 @@
+//! 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) {}
+//! }
+//! # fn main() {}
+//! ```
+//!
+//! [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::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;
+/// extern crate env_logger;
+///
+/// use std::env;
+/// use std::io;
+/// use env_logger::filter::Builder;
+///
+/// fn main() {
+/// 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: Vec<Directive>,
+ 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
+ /// extern crate log;
+ /// extern crate env_logger;
+ ///
+ /// use log::LevelFilter;
+ /// use env_logger::filter::Builder;
+ ///
+ /// fn main() {
+ /// 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: Vec::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.push(Directive {
+ name: 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.push(directive);
+ }
+ self
+ }
+
+ /// Build a log filter.
+ pub fn build(&mut self) -> Filter {
+ assert!(!self.built, "attempt to re-use consumed builder");
+ self.built = true;
+
+ if self.directives.is_empty() {
+ // Adds the default filter if none exist
+ self.directives.push(Directive {
+ name: None,
+ level: LevelFilter::Error,
+ });
+ } else {
+ // Sort the directives by length of their name, this allows a
+ // little more efficient lookup at runtime.
+ self.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::replace(&mut self.directives, Vec::new()),
+ 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);
+ }
+ mods.map(|m| {
+ for s in m.split(',') {
+ if s.len() == 0 {
+ 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.map_or(None, |filter| match inner::Filter::new(filter) {
+ Ok(re) => Some(re),
+ Err(e) => {
+ eprintln!("warning: invalid regex filter - {}", e);
+ None
+ }
+ });
+
+ return (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"));
+ }
+
+ #[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 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_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_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");
+ }
+}
diff --git a/vendor/env_logger-0.7.1/src/filter/regex.rs b/vendor/env_logger-0.7.1/src/filter/regex.rs
new file mode 100644
index 000000000..fb21528a1
--- /dev/null
+++ b/vendor/env_logger-0.7.1/src/filter/regex.rs
@@ -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)
+ }
+}
diff --git a/vendor/env_logger-0.7.1/src/filter/string.rs b/vendor/env_logger-0.7.1/src/filter/string.rs
new file mode 100644
index 000000000..ea476e42f
--- /dev/null
+++ b/vendor/env_logger-0.7.1/src/filter/string.rs
@@ -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)
+ }
+}
diff --git a/vendor/env_logger-0.7.1/src/fmt/humantime/extern_impl.rs b/vendor/env_logger-0.7.1/src/fmt/humantime/extern_impl.rs
new file mode 100644
index 000000000..19dec1b65
--- /dev/null
+++ b/vendor/env_logger-0.7.1/src/fmt/humantime/extern_impl.rs
@@ -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)
+ }
+}
diff --git a/vendor/env_logger-0.7.1/src/fmt/humantime/mod.rs b/vendor/env_logger-0.7.1/src/fmt/humantime/mod.rs
new file mode 100644
index 000000000..ac23ae249
--- /dev/null
+++ b/vendor/env_logger-0.7.1/src/fmt/humantime/mod.rs
@@ -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::*;
diff --git a/vendor/env_logger-0.7.1/src/fmt/humantime/shim_impl.rs b/vendor/env_logger-0.7.1/src/fmt/humantime/shim_impl.rs
new file mode 100644
index 000000000..906bf9e4c
--- /dev/null
+++ b/vendor/env_logger-0.7.1/src/fmt/humantime/shim_impl.rs
@@ -0,0 +1,5 @@
+/*
+Timestamps aren't available when we don't have a `humantime` dependency.
+*/
+
+pub(in crate::fmt) mod glob {}
diff --git a/vendor/env_logger-0.7.1/src/fmt/mod.rs b/vendor/env_logger-0.7.1/src/fmt/mod.rs
new file mode 100644
index 000000000..e699e214d
--- /dev/null
+++ b/vendor/env_logger-0.7.1/src/fmt/mod.rs
@@ -0,0 +1,489 @@
+//! 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) struct Builder {
+ pub format_timestamp: Option<TimestampPrecision>,
+ pub format_module_path: bool,
+ pub format_level: bool,
+ pub format_indent: Option<usize>,
+ #[allow(unknown_lints, bare_trait_objects)]
+ pub custom_format: Option<Box<Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send>>,
+ built: bool,
+}
+
+impl Default for Builder {
+ fn default() -> Self {
+ Builder {
+ format_timestamp: Some(Default::default()),
+ format_module_path: true,
+ format_level: true,
+ format_indent: Some(4),
+ custom_format: None,
+ 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.
+ #[allow(unknown_lints, bare_trait_objects)]
+ pub fn build(&mut self) -> Box<Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send> {
+ 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,
+ level: built.format_level,
+ written_header_value: false,
+ indent: built.format_indent,
+ 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,
+ level: bool,
+ written_header_value: bool,
+ indent: Option<usize>,
+ buf: &'a mut Formatter,
+}
+
+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.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)
+ .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 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 => writeln!(self.buf, "{}", record.args()),
+
+ 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, "\n{:width$}", "", 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())?;
+ }
+
+ writeln!(self.buf)?;
+
+ Ok(())
+ }
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ use log::{Level, Record};
+
+ fn write(fmt: DefaultFormat) -> String {
+ let buf = fmt.buf.buf.clone();
+
+ let record = Record::builder()
+ .args(format_args!("log\nmessage"))
+ .level(Level::Info)
+ .file(Some("test.rs"))
+ .line(Some(144))
+ .module_path(Some("test::path"))
+ .build();
+
+ fmt.write(&record).expect("failed to write record");
+
+ let buf = buf.borrow();
+ String::from_utf8(buf.bytes().to_vec()).expect("failed to read record")
+ }
+
+ #[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,
+ level: true,
+ written_header_value: false,
+ indent: None,
+ 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,
+ level: false,
+ written_header_value: false,
+ indent: None,
+ 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,
+ level: true,
+ written_header_value: false,
+ indent: Some(4),
+ 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,
+ level: true,
+ written_header_value: false,
+ indent: Some(0),
+ 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,
+ level: false,
+ written_header_value: false,
+ indent: Some(4),
+ buf: &mut f,
+ });
+
+ assert_eq!("log\n message\n", written);
+ }
+}
diff --git a/vendor/env_logger-0.7.1/src/fmt/writer/atty.rs b/vendor/env_logger-0.7.1/src/fmt/writer/atty.rs
new file mode 100644
index 000000000..f6718413f
--- /dev/null
+++ b/vendor/env_logger-0.7.1/src/fmt/writer/atty.rs
@@ -0,0 +1,34 @@
+/*
+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 {
+ use atty;
+
+ 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::*;
diff --git a/vendor/env_logger-0.7.1/src/fmt/writer/mod.rs b/vendor/env_logger-0.7.1/src/fmt/writer/mod.rs
new file mode 100644
index 000000000..6ee63a398
--- /dev/null
+++ b/vendor/env_logger-0.7.1/src/fmt/writer/mod.rs
@@ -0,0 +1,201 @@
+mod atty;
+mod termcolor;
+
+use self::atty::{is_stderr, is_stdout};
+use self::termcolor::BufferWriter;
+use std::{fmt, io};
+
+pub(in crate::fmt) mod glob {
+ pub use super::termcolor::glob::*;
+ pub use super::*;
+}
+
+pub(in crate::fmt) use self::termcolor::Buffer;
+
+/// Log target, either `stdout` or `stderr`.
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+pub enum Target {
+ /// Logs will be sent to standard output.
+ Stdout,
+ /// Logs will be sent to standard error.
+ Stderr,
+}
+
+impl Default for Target {
+ fn default() -> Self {
+ Target::Stderr
+ }
+}
+
+/// 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(in crate::fmt) fn buffer(&self) -> Buffer {
+ self.inner.buffer()
+ }
+
+ pub(in crate::fmt) 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.
+pub(crate) struct Builder {
+ target: Target,
+ 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;
+ 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 {
+ Target::Stderr => is_stderr(),
+ Target::Stdout => is_stdout(),
+ } {
+ WriteStyle::Auto
+ } else {
+ WriteStyle::Never
+ }
+ }
+ color_choice => color_choice,
+ };
+
+ let writer = match self.target {
+ Target::Stderr => BufferWriter::stderr(self.is_test, color_choice),
+ Target::Stdout => BufferWriter::stdout(self.is_test, color_choice),
+ };
+
+ Writer {
+ inner: writer,
+ write_style: self.write_style,
+ }
+ }
+}
+
+impl Default for Builder {
+ fn default() -> Self {
+ Builder::new()
+ }
+}
+
+impl fmt::Debug for Builder {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Logger")
+ .field("target", &self.target)
+ .field("write_style", &self.write_style)
+ .finish()
+ }
+}
+
+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));
+ }
+ }
+}
diff --git a/vendor/env_logger-0.7.1/src/fmt/writer/termcolor/extern_impl.rs b/vendor/env_logger-0.7.1/src/fmt/writer/termcolor/extern_impl.rs
new file mode 100644
index 000000000..2d38e375a
--- /dev/null
+++ b/vendor/env_logger-0.7.1/src/fmt/writer/termcolor/extern_impl.rs
@@ -0,0 +1,486 @@
+use std::borrow::Cow;
+use std::cell::RefCell;
+use std::fmt;
+use std::io::{self, Write};
+use std::rc::Rc;
+
+use log::Level;
+use termcolor::{self, ColorChoice, ColorSpec, WriteColor};
+
+use crate::fmt::{Formatter, Target, 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::Black).set_intense(true),
+ Level::Debug => level_style.set_color(Color::White),
+ 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,
+ test_target: Option<Target>,
+}
+
+pub(in crate::fmt) struct Buffer {
+ inner: termcolor::Buffer,
+ test_target: Option<Target>,
+}
+
+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()),
+ test_target: if is_test { Some(Target::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()),
+ test_target: if is_test { Some(Target::Stdout) } else { None },
+ }
+ }
+
+ pub(in crate::fmt::writer) fn buffer(&self) -> Buffer {
+ Buffer {
+ inner: self.inner.buffer(),
+ test_target: self.test_target,
+ }
+ }
+
+ pub(in crate::fmt::writer) fn print(&self, buf: &Buffer) -> io::Result<()> {
+ if let Some(target) = self.test_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 {
+ Target::Stderr => eprint!("{}", log),
+ Target::Stdout => print!("{}", 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.test_target.is_none() {
+ 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.test_target.is_none() {
+ 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(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 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(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>(&mut self, value: T) -> StyledValue<'static, T> {
+ StyledValue {
+ style: Cow::Owned(self.clone()),
+ 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/ripgrep/tree/master/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)]
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Color {
+ Black,
+ Blue,
+ Green,
+ Red,
+ Cyan,
+ Magenta,
+ Yellow,
+ White,
+ Ansi256(u8),
+ Rgb(u8, u8, u8),
+ #[doc(hidden)]
+ __Nonexhaustive,
+}
+
+impl Color {
+ fn into_termcolor(self) -> Option<termcolor::Color> {
+ match self {
+ Color::Black => Some(termcolor::Color::Black),
+ Color::Blue => Some(termcolor::Color::Blue),
+ Color::Green => Some(termcolor::Color::Green),
+ Color::Red => Some(termcolor::Color::Red),
+ Color::Cyan => Some(termcolor::Color::Cyan),
+ Color::Magenta => Some(termcolor::Color::Magenta),
+ Color::Yellow => Some(termcolor::Color::Yellow),
+ Color::White => Some(termcolor::Color::White),
+ Color::Ansi256(value) => Some(termcolor::Color::Ansi256(value)),
+ Color::Rgb(r, g, b) => Some(termcolor::Color::Rgb(r, g, b)),
+ _ => None,
+ }
+ }
+}
diff --git a/vendor/env_logger-0.7.1/src/fmt/writer/termcolor/mod.rs b/vendor/env_logger-0.7.1/src/fmt/writer/termcolor/mod.rs
new file mode 100644
index 000000000..f3e6768cd
--- /dev/null
+++ b/vendor/env_logger-0.7.1/src/fmt/writer/termcolor/mod.rs
@@ -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::*;
diff --git a/vendor/env_logger-0.7.1/src/fmt/writer/termcolor/shim_impl.rs b/vendor/env_logger-0.7.1/src/fmt/writer/termcolor/shim_impl.rs
new file mode 100644
index 000000000..563f8ad4f
--- /dev/null
+++ b/vendor/env_logger-0.7.1/src/fmt/writer/termcolor/shim_impl.rs
@@ -0,0 +1,63 @@
+use std::io;
+
+use crate::fmt::{Target, WriteStyle};
+
+pub(in crate::fmt::writer) mod glob {}
+
+pub(in crate::fmt::writer) struct BufferWriter {
+ target: Target,
+}
+
+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: Target::Stderr,
+ }
+ }
+
+ pub(in crate::fmt::writer) fn stdout(_is_test: bool, _write_style: WriteStyle) -> Self {
+ BufferWriter {
+ target: Target::Stdout,
+ }
+ }
+
+ 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`
+ let log = String::from_utf8_lossy(&buf.0);
+
+ match self.target {
+ Target::Stderr => eprint!("{}", log),
+ Target::Stdout => print!("{}", log),
+ }
+
+ 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
+ }
+}
diff --git a/vendor/env_logger-0.7.1/src/lib.rs b/vendor/env_logger-0.7.1/src/lib.rs
new file mode 100644
index 000000000..415183600
--- /dev/null
+++ b/vendor/env_logger-0.7.1/src/lib.rs
@@ -0,0 +1,1177 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! A simple logger configured via environment variables which writes
+//! to stdout or stderr, for use with the logging facade exposed by the
+//! [`log` crate][log-crate-url].
+//!
+//! ## Example
+//!
+//! ```
+//! #[macro_use] extern crate log;
+//!
+//! use log::Level;
+//!
+//! fn main() {
+//! env_logger::init();
+//!
+//! debug!("this is a debug {}", "message");
+//! error!("this is printed by default");
+//!
+//! if log_enabled!(Level::Info) {
+//! let x = 3 * 4; // expensive computation
+//! info!("the answer was: {}", x);
+//! }
+//! }
+//! ```
+//!
+//! Assumes the binary is `main`:
+//!
+//! ```{.bash}
+//! $ RUST_LOG=error ./main
+//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
+//! ```
+//!
+//! ```{.bash}
+//! $ RUST_LOG=info ./main
+//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
+//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
+//! ```
+//!
+//! ```{.bash}
+//! $ RUST_LOG=debug ./main
+//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message
+//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
+//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
+//! ```
+//!
+//! You can also set the log level on a per module basis:
+//!
+//! ```{.bash}
+//! $ RUST_LOG=main=info ./main
+//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
+//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
+//! ```
+//!
+//! And enable all logging:
+//!
+//! ```{.bash}
+//! $ RUST_LOG=main ./main
+//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message
+//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
+//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
+//! ```
+//!
+//! If the binary name contains hyphens, you will need to replace
+//! them with underscores:
+//!
+//! ```{.bash}
+//! $ RUST_LOG=my_app ./my-app
+//! [2017-11-09T02:12:24Z DEBUG my_app] this is a debug message
+//! [2017-11-09T02:12:24Z ERROR my_app] this is printed by default
+//! [2017-11-09T02:12:24Z INFO my_app] the answer was: 12
+//! ```
+//!
+//! This is because Rust modules and crates cannot contain hyphens
+//! in their name, although `cargo` continues to accept them.
+//!
+//! See the documentation for the [`log` crate][log-crate-url] for more
+//! information about its API.
+//!
+//! ## Enabling logging
+//!
+//! Log levels are controlled on a per-module basis, and by default all logging
+//! is disabled except for `error!`. Logging is controlled via the `RUST_LOG`
+//! environment variable. The value of this environment variable is a
+//! comma-separated list of logging directives. A logging directive is of the
+//! form:
+//!
+//! ```text
+//! path::to::module=level
+//! ```
+//!
+//! The path to the module is rooted in the name of the crate it was compiled
+//! for, so if your program is contained in a file `hello.rs`, for example, to
+//! turn on logging for this file you would use a value of `RUST_LOG=hello`.
+//! Furthermore, this path is a prefix-search, so all modules nested in the
+//! specified module will also have logging enabled.
+//!
+//! The actual `level` is optional to specify. If omitted, all logging will
+//! be enabled. If specified, it must be one of the strings `debug`, `error`,
+//! `info`, `warn`, or `trace`.
+//!
+//! As the log level for a module is optional, the module to enable logging for
+//! is also optional. If only a `level` is provided, then the global log
+//! level for all modules is set to this value.
+//!
+//! Some examples of valid values of `RUST_LOG` are:
+//!
+//! * `hello` turns on all logging for the 'hello' module
+//! * `info` turns on all info logging
+//! * `hello=debug` turns on debug logging for 'hello'
+//! * `hello,std::option` turns on hello, and std's option logging
+//! * `error,hello=warn` turn on global error logging and also warn for hello
+//!
+//! ## Filtering results
+//!
+//! A `RUST_LOG` directive may include a regex filter. The syntax is to append `/`
+//! followed by a regex. Each message is checked against the regex, and is only
+//! logged if it matches. Note that the matching is done after formatting the
+//! log string but before adding any logging meta-data. There is a single filter
+//! for all modules.
+//!
+//! Some examples:
+//!
+//! * `hello/foo` turns on all logging for the 'hello' module where the log
+//! message includes 'foo'.
+//! * `info/f.o` turns on all info logging where the log message includes 'foo',
+//! 'f1o', 'fao', etc.
+//! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the log
+//! message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc.
+//! * `error,hello=warn/[0-9]scopes` turn on global error logging and also
+//! warn for hello. In both cases the log message must include a single digit
+//! number followed by 'scopes'.
+//!
+//! ## Capturing logs in tests
+//!
+//! Records logged during `cargo test` will not be captured by the test harness by default.
+//! The [`Builder::is_test`] method can be used in unit tests to ensure logs will be captured:
+//!
+//! ```
+//! # #[macro_use] extern crate log;
+//! # fn main() {}
+//! #[cfg(test)]
+//! mod tests {
+//! fn init() {
+//! let _ = env_logger::builder().is_test(true).try_init();
+//! }
+//!
+//! #[test]
+//! fn it_works() {
+//! init();
+//!
+//! info!("This record will be captured by `cargo test`");
+//!
+//! assert_eq!(2, 1 + 1);
+//! }
+//! }
+//! ```
+//!
+//! Enabling test capturing comes at the expense of color and other style support
+//! and may have performance implications.
+//!
+//! ## Disabling colors
+//!
+//! Colors and other styles can be configured with the `RUST_LOG_STYLE`
+//! environment variable. It accepts the following values:
+//!
+//! * `auto` (default) will attempt to print style characters, but don't force the issue.
+//! If the console isn't available on Windows, or if TERM=dumb, for example, then don't print colors.
+//! * `always` will always print style characters even if they aren't supported by the terminal.
+//! This includes emitting ANSI colors on Windows if the console API is unavailable.
+//! * `never` will never print style characters.
+//!
+//! ## Tweaking the default format
+//!
+//! Parts of the default format can be excluded from the log output using the [`Builder`].
+//! The following example excludes the timestamp from the log output:
+//!
+//! ```
+//! env_logger::builder()
+//! .format_timestamp(None)
+//! .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.
+//!
+//! ### Using a custom format
+//!
+//! Custom formats can be provided as closures to the [`Builder`].
+//! These closures take a [`Formatter`] and `log::Record` as arguments:
+//!
+//! ```
+//! use std::io::Write;
+//!
+//! env_logger::builder()
+//! .format(|buf, record| {
+//! writeln!(buf, "{}: {}", record.level(), record.args())
+//! })
+//! .init();
+//! ```
+//!
+//! See the [`fmt`] module for more details about custom formats.
+//!
+//! ## Specifying defaults for environment variables
+//!
+//! `env_logger` can read configuration from environment variables.
+//! If these variables aren't present, the default value to use can be tweaked with the [`Env`] type.
+//! The following example defaults to log `warn` and above if the `RUST_LOG` environment variable
+//! isn't set:
+//!
+//! ```
+//! use env_logger::Env;
+//!
+//! env_logger::from_env(Env::default().default_filter_or("warn")).init();
+//! ```
+//!
+//! [log-crate-url]: https://docs.rs/log/
+//! [`Builder`]: struct.Builder.html
+//! [`Builder::is_test`]: struct.Builder.html#method.is_test
+//! [`Env`]: struct.Env.html
+//! [`fmt`]: fmt/index.html
+
+#![doc(
+ html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "https://www.rust-lang.org/static/images/favicon.ico",
+ html_root_url = "https://docs.rs/env_logger/0.7.1"
+)]
+#![cfg_attr(test, deny(warnings))]
+// When compiled for the rustc compiler itself we want to make sure that this is
+// an unstable crate
+#![cfg_attr(rustbuild, feature(staged_api, rustc_private))]
+#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))]
+#![deny(missing_debug_implementations, missing_docs, warnings)]
+
+use std::{borrow::Cow, cell::RefCell, env, io};
+
+use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};
+
+pub mod filter;
+pub mod fmt;
+
+pub use self::fmt::glob::*;
+
+use self::filter::Filter;
+use self::fmt::writer::{self, Writer};
+use self::fmt::Formatter;
+
+/// The default name for the environment variable to read filters from.
+pub const DEFAULT_FILTER_ENV: &'static str = "RUST_LOG";
+
+/// The default name for the environment variable to read style preferences from.
+pub const DEFAULT_WRITE_STYLE_ENV: &'static str = "RUST_LOG_STYLE";
+
+/// Set of environment variables to configure from.
+///
+/// # Default environment variables
+///
+/// By default, the `Env` will read the following environment variables:
+///
+/// - `RUST_LOG`: the level filter
+/// - `RUST_LOG_STYLE`: whether or not to print styles with records.
+///
+/// These sources can be configured using the builder methods on `Env`.
+#[derive(Debug)]
+pub struct Env<'a> {
+ filter: Var<'a>,
+ write_style: Var<'a>,
+}
+
+#[derive(Debug)]
+struct Var<'a> {
+ name: Cow<'a, str>,
+ default: Option<Cow<'a, str>>,
+}
+
+/// The env logger.
+///
+/// This struct implements the `Log` trait from the [`log` crate][log-crate-url],
+/// which allows it to act as a logger.
+///
+/// The [`init()`], [`try_init()`], [`Builder::init()`] and [`Builder::try_init()`]
+/// methods will each construct a `Logger` and immediately initialize it as the
+/// default global logger.
+///
+/// If you'd instead need access to the constructed `Logger`, you can use
+/// the associated [`Builder`] and install it with the
+/// [`log` crate][log-crate-url] directly.
+///
+/// [log-crate-url]: https://docs.rs/log/
+/// [`init()`]: fn.init.html
+/// [`try_init()`]: fn.try_init.html
+/// [`Builder::init()`]: struct.Builder.html#method.init
+/// [`Builder::try_init()`]: struct.Builder.html#method.try_init
+/// [`Builder`]: struct.Builder.html
+pub struct Logger {
+ writer: Writer,
+ filter: Filter,
+ #[allow(unknown_lints, bare_trait_objects)]
+ format: Box<Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send>,
+}
+
+/// `Builder` acts as builder for initializing a `Logger`.
+///
+/// It can be used to customize the log format, change the environment variable used
+/// to provide the logging directives and also set the default log level filter.
+///
+/// # Examples
+///
+/// ```
+/// #[macro_use] extern crate log;
+///
+/// use std::env;
+/// use std::io::Write;
+/// use log::LevelFilter;
+/// use env_logger::Builder;
+///
+/// fn main() {
+/// let mut builder = Builder::from_default_env();
+///
+/// builder.format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args()))
+/// .filter(None, LevelFilter::Info)
+/// .init();
+///
+/// error!("error message");
+/// info!("info message");
+/// }
+/// ```
+#[derive(Default)]
+pub struct Builder {
+ filter: filter::Builder,
+ writer: writer::Builder,
+ format: fmt::Builder,
+ built: bool,
+}
+
+impl Builder {
+ /// Initializes the log builder with defaults.
+ ///
+ /// **NOTE:** This method won't read from any environment variables.
+ /// Use the [`filter`] and [`write_style`] methods to configure the builder
+ /// or use [`from_env`] or [`from_default_env`] instead.
+ ///
+ /// # Examples
+ ///
+ /// Create a new builder and configure filters and style:
+ ///
+ /// ```
+ /// # fn main() {
+ /// use log::LevelFilter;
+ /// use env_logger::{Builder, WriteStyle};
+ ///
+ /// let mut builder = Builder::new();
+ ///
+ /// builder.filter(None, LevelFilter::Info)
+ /// .write_style(WriteStyle::Always)
+ /// .init();
+ /// # }
+ /// ```
+ ///
+ /// [`filter`]: #method.filter
+ /// [`write_style`]: #method.write_style
+ /// [`from_env`]: #method.from_env
+ /// [`from_default_env`]: #method.from_default_env
+ pub fn new() -> Builder {
+ Default::default()
+ }
+
+ /// Initializes the log builder from the environment.
+ ///
+ /// The variables used to read configuration from can be tweaked before
+ /// passing in.
+ ///
+ /// # Examples
+ ///
+ /// Initialise a logger reading the log filter from an environment variable
+ /// called `MY_LOG`:
+ ///
+ /// ```
+ /// use env_logger::Builder;
+ ///
+ /// let mut builder = Builder::from_env("MY_LOG");
+ /// builder.init();
+ /// ```
+ ///
+ /// Initialise a logger using the `MY_LOG` variable for filtering and
+ /// `MY_LOG_STYLE` for whether or not to write styles:
+ ///
+ /// ```
+ /// use env_logger::{Builder, Env};
+ ///
+ /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
+ ///
+ /// let mut builder = Builder::from_env(env);
+ /// builder.init();
+ /// ```
+ pub fn from_env<'a, E>(env: E) -> Self
+ where
+ E: Into<Env<'a>>,
+ {
+ let mut builder = Builder::new();
+ let env = env.into();
+
+ if let Some(s) = env.get_filter() {
+ builder.parse_filters(&s);
+ }
+
+ if let Some(s) = env.get_write_style() {
+ builder.parse_write_style(&s);
+ }
+
+ builder
+ }
+
+ /// Initializes the log builder from the environment using default variable names.
+ ///
+ /// This method is a convenient way to call `from_env(Env::default())` without
+ /// having to use the `Env` type explicitly. The builder will use the
+ /// [default environment variables].
+ ///
+ /// # Examples
+ ///
+ /// Initialise a logger using the default environment variables:
+ ///
+ /// ```
+ /// use env_logger::Builder;
+ ///
+ /// let mut builder = Builder::from_default_env();
+ /// builder.init();
+ /// ```
+ ///
+ /// [default environment variables]: struct.Env.html#default-environment-variables
+ pub fn from_default_env() -> Self {
+ Self::from_env(Env::default())
+ }
+
+ /// Sets the format function for formatting the log output.
+ ///
+ /// This function is called on each record logged and should format the
+ /// log record and output it to the given [`Formatter`].
+ ///
+ /// The format function is expected to output the string directly to the
+ /// `Formatter` so that implementations can use the [`std::fmt`] macros
+ /// to format and output without intermediate heap allocations. The default
+ /// `env_logger` formatter takes advantage of this.
+ ///
+ /// # Examples
+ ///
+ /// Use a custom format to write only the log message:
+ ///
+ /// ```
+ /// use std::io::Write;
+ /// use env_logger::Builder;
+ ///
+ /// let mut builder = Builder::new();
+ ///
+ /// builder.format(|buf, record| writeln!(buf, "{}", record.args()));
+ /// ```
+ ///
+ /// [`Formatter`]: fmt/struct.Formatter.html
+ /// [`String`]: https://doc.rust-lang.org/stable/std/string/struct.String.html
+ /// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html
+ pub fn format<F: 'static>(&mut self, format: F) -> &mut Self
+ where
+ F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send,
+ {
+ self.format.custom_format = Some(Box::new(format));
+ self
+ }
+
+ /// Use the default format.
+ ///
+ /// This method will clear any custom format set on the builder.
+ pub fn default_format(&mut self) -> &mut Self {
+ self.format = Default::default();
+ self
+ }
+
+ /// Whether or not to write the level in the default format.
+ pub fn format_level(&mut self, write: bool) -> &mut Self {
+ self.format.format_level = write;
+ self
+ }
+
+ /// Whether or not to write the module path in the default format.
+ pub fn format_module_path(&mut self, write: bool) -> &mut Self {
+ self.format.format_module_path = write;
+ self
+ }
+
+ /// Configures the amount of spaces to use to indent multiline log records.
+ /// A value of `None` disables any kind of indentation.
+ pub fn format_indent(&mut self, indent: Option<usize>) -> &mut Self {
+ self.format.format_indent = indent;
+ self
+ }
+
+ /// Configures if timestamp should be included and in what precision.
+ pub fn format_timestamp(&mut self, timestamp: Option<fmt::TimestampPrecision>) -> &mut Self {
+ self.format.format_timestamp = timestamp;
+ self
+ }
+
+ /// Configures the timestamp to use second precision.
+ pub fn format_timestamp_secs(&mut self) -> &mut Self {
+ self.format_timestamp(Some(fmt::TimestampPrecision::Seconds))
+ }
+
+ /// Configures the timestamp to use millisecond precision.
+ pub fn format_timestamp_millis(&mut self) -> &mut Self {
+ self.format_timestamp(Some(fmt::TimestampPrecision::Millis))
+ }
+
+ /// Configures the timestamp to use microsecond precision.
+ pub fn format_timestamp_micros(&mut self) -> &mut Self {
+ self.format_timestamp(Some(fmt::TimestampPrecision::Micros))
+ }
+
+ /// Configures the timestamp to use nanosecond precision.
+ pub fn format_timestamp_nanos(&mut self) -> &mut Self {
+ self.format_timestamp(Some(fmt::TimestampPrecision::Nanos))
+ }
+
+ /// Adds a directive to the filter for a specific module.
+ ///
+ /// # Examples
+ ///
+ /// Only include messages for warning and above for logs in `path::to::module`:
+ ///
+ /// ```
+ /// # fn main() {
+ /// use log::LevelFilter;
+ /// use env_logger::Builder;
+ ///
+ /// let mut builder = Builder::new();
+ ///
+ /// builder.filter_module("path::to::module", LevelFilter::Info);
+ /// # }
+ /// ```
+ pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self {
+ self.filter.filter_module(module, level);
+ self
+ }
+
+ /// Adds a directive to the filter for all modules.
+ ///
+ /// # Examples
+ ///
+ /// Only include messages for warning and above for logs in `path::to::module`:
+ ///
+ /// ```
+ /// # fn main() {
+ /// use log::LevelFilter;
+ /// use env_logger::Builder;
+ ///
+ /// let mut builder = Builder::new();
+ ///
+ /// builder.filter_level(LevelFilter::Info);
+ /// # }
+ /// ```
+ pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self {
+ self.filter.filter_level(level);
+ self
+ }
+
+ /// Adds filters to the logger.
+ ///
+ /// 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.
+ ///
+ /// # Examples
+ ///
+ /// Only include messages for warning and above for logs in `path::to::module`:
+ ///
+ /// ```
+ /// # fn main() {
+ /// use log::LevelFilter;
+ /// use env_logger::Builder;
+ ///
+ /// let mut builder = Builder::new();
+ ///
+ /// builder.filter(Some("path::to::module"), LevelFilter::Info);
+ /// # }
+ /// ```
+ pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self {
+ self.filter.filter(module, level);
+ self
+ }
+
+ /// Parses the directives string in the same form as the `RUST_LOG`
+ /// environment variable.
+ ///
+ /// See the module documentation for more details.
+ pub fn parse_filters(&mut self, filters: &str) -> &mut Self {
+ self.filter.parse(filters);
+ self
+ }
+
+ /// Sets the target for the log output.
+ ///
+ /// Env logger can log to either stdout or stderr. The default is stderr.
+ ///
+ /// # Examples
+ ///
+ /// Write log message to `stdout`:
+ ///
+ /// ```
+ /// use env_logger::{Builder, Target};
+ ///
+ /// let mut builder = Builder::new();
+ ///
+ /// builder.target(Target::Stdout);
+ /// ```
+ pub fn target(&mut self, target: fmt::Target) -> &mut Self {
+ self.writer.target(target);
+ self
+ }
+
+ /// Sets whether or not styles will be written.
+ ///
+ /// This can be useful in environments that don't support control characters
+ /// for setting colors.
+ ///
+ /// # Examples
+ ///
+ /// Never attempt to write styles:
+ ///
+ /// ```
+ /// use env_logger::{Builder, WriteStyle};
+ ///
+ /// let mut builder = Builder::new();
+ ///
+ /// builder.write_style(WriteStyle::Never);
+ /// ```
+ pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self {
+ self.writer.write_style(write_style);
+ self
+ }
+
+ /// Parses whether or not to write styles in the same form as the `RUST_LOG_STYLE`
+ /// environment variable.
+ ///
+ /// See the module documentation for more details.
+ pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self {
+ self.writer.parse_write_style(write_style);
+ self
+ }
+
+ /// Sets whether or not the logger will be used in unit tests.
+ ///
+ /// If `is_test` is `true` then the logger will allow the testing framework to
+ /// capture log records rather than printing them to the terminal directly.
+ pub fn is_test(&mut self, is_test: bool) -> &mut Self {
+ self.writer.is_test(is_test);
+ self
+ }
+
+ /// Initializes the global logger with the built env logger.
+ ///
+ /// This should be called early in the execution of a Rust program. Any log
+ /// events that occur before initialization will be ignored.
+ ///
+ /// # Errors
+ ///
+ /// This function will fail if it is called more than once, or if another
+ /// library has already initialized a global logger.
+ pub fn try_init(&mut self) -> Result<(), SetLoggerError> {
+ let logger = self.build();
+
+ let max_level = logger.filter();
+ let r = log::set_boxed_logger(Box::new(logger));
+
+ if r.is_ok() {
+ log::set_max_level(max_level);
+ }
+
+ r
+ }
+
+ /// Initializes the global logger with the built env logger.
+ ///
+ /// This should be called early in the execution of a Rust program. Any log
+ /// events that occur before initialization will be ignored.
+ ///
+ /// # Panics
+ ///
+ /// This function will panic if it is called more than once, or if another
+ /// library has already initialized a global logger.
+ pub fn init(&mut self) {
+ self.try_init()
+ .expect("Builder::init should not be called after logger initialized");
+ }
+
+ /// Build an env logger.
+ ///
+ /// The returned logger implements the `Log` trait and can be installed manually
+ /// or nested within another logger.
+ pub fn build(&mut self) -> Logger {
+ assert!(!self.built, "attempt to re-use consumed builder");
+ self.built = true;
+
+ Logger {
+ writer: self.writer.build(),
+ filter: self.filter.build(),
+ format: self.format.build(),
+ }
+ }
+}
+
+impl Logger {
+ /// Creates the logger from the environment.
+ ///
+ /// The variables used to read configuration from can be tweaked before
+ /// passing in.
+ ///
+ /// # Examples
+ ///
+ /// Create a logger reading the log filter from an environment variable
+ /// called `MY_LOG`:
+ ///
+ /// ```
+ /// use env_logger::Logger;
+ ///
+ /// let logger = Logger::from_env("MY_LOG");
+ /// ```
+ ///
+ /// Create a logger using the `MY_LOG` variable for filtering and
+ /// `MY_LOG_STYLE` for whether or not to write styles:
+ ///
+ /// ```
+ /// use env_logger::{Logger, Env};
+ ///
+ /// let env = Env::new().filter_or("MY_LOG", "info").write_style_or("MY_LOG_STYLE", "always");
+ ///
+ /// let logger = Logger::from_env(env);
+ /// ```
+ pub fn from_env<'a, E>(env: E) -> Self
+ where
+ E: Into<Env<'a>>,
+ {
+ Builder::from_env(env).build()
+ }
+
+ /// Creates the logger from the environment using default variable names.
+ ///
+ /// This method is a convenient way to call `from_env(Env::default())` without
+ /// having to use the `Env` type explicitly. The logger will use the
+ /// [default environment variables].
+ ///
+ /// # Examples
+ ///
+ /// Creates a logger using the default environment variables:
+ ///
+ /// ```
+ /// use env_logger::Logger;
+ ///
+ /// let logger = Logger::from_default_env();
+ /// ```
+ ///
+ /// [default environment variables]: struct.Env.html#default-environment-variables
+ pub fn from_default_env() -> Self {
+ Builder::from_default_env().build()
+ }
+
+ /// Returns the maximum `LevelFilter` that this env logger instance is
+ /// configured to output.
+ pub fn filter(&self) -> LevelFilter {
+ self.filter.filter()
+ }
+
+ /// Checks if this record matches the configured filter.
+ pub fn matches(&self, record: &Record) -> bool {
+ self.filter.matches(record)
+ }
+}
+
+impl Log for Logger {
+ fn enabled(&self, metadata: &Metadata) -> bool {
+ self.filter.enabled(metadata)
+ }
+
+ fn log(&self, record: &Record) {
+ if self.matches(record) {
+ // Log records are written to a thread-local buffer before being printed
+ // to the terminal. We clear these buffers afterwards, but they aren't shrinked
+ // so will always at least have capacity for the largest log record formatted
+ // on that thread.
+ //
+ // If multiple `Logger`s are used by the same threads then the thread-local
+ // formatter might have different color support. If this is the case the
+ // formatter and its buffer are discarded and recreated.
+
+ thread_local! {
+ static FORMATTER: RefCell<Option<Formatter>> = RefCell::new(None);
+ }
+
+ let print = |formatter: &mut Formatter, record: &Record| {
+ let _ =
+ (self.format)(formatter, record).and_then(|_| formatter.print(&self.writer));
+
+ // Always clear the buffer afterwards
+ formatter.clear();
+ };
+
+ let printed = FORMATTER
+ .try_with(|tl_buf| {
+ match tl_buf.try_borrow_mut() {
+ // There are no active borrows of the buffer
+ Ok(mut tl_buf) => match *tl_buf {
+ // We have a previously set formatter
+ Some(ref mut formatter) => {
+ // Check the buffer style. If it's different from the logger's
+ // style then drop the buffer and recreate it.
+ if formatter.write_style() != self.writer.write_style() {
+ *formatter = Formatter::new(&self.writer);
+ }
+
+ print(formatter, record);
+ }
+ // We don't have a previously set formatter
+ None => {
+ let mut formatter = Formatter::new(&self.writer);
+ print(&mut formatter, record);
+
+ *tl_buf = Some(formatter);
+ }
+ },
+ // There's already an active borrow of the buffer (due to re-entrancy)
+ Err(_) => {
+ print(&mut Formatter::new(&self.writer), record);
+ }
+ }
+ })
+ .is_ok();
+
+ if !printed {
+ // The thread-local storage was not available (because its
+ // destructor has already run). Create a new single-use
+ // Formatter on the stack for this call.
+ print(&mut Formatter::new(&self.writer), record);
+ }
+ }
+ }
+
+ fn flush(&self) {}
+}
+
+impl<'a> Env<'a> {
+ /// Get a default set of environment variables.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Specify an environment variable to read the filter from.
+ pub fn filter<E>(mut self, filter_env: E) -> Self
+ where
+ E: Into<Cow<'a, str>>,
+ {
+ self.filter = Var::new(filter_env);
+
+ self
+ }
+
+ /// Specify an environment variable to read the filter from.
+ ///
+ /// If the variable is not set, the default value will be used.
+ pub fn filter_or<E, V>(mut self, filter_env: E, default: V) -> Self
+ where
+ E: Into<Cow<'a, str>>,
+ V: Into<Cow<'a, str>>,
+ {
+ self.filter = Var::new_with_default(filter_env, default);
+
+ self
+ }
+
+ /// Use the default environment variable to read the filter from.
+ ///
+ /// If the variable is not set, the default value will be used.
+ pub fn default_filter_or<V>(mut self, default: V) -> Self
+ where
+ V: Into<Cow<'a, str>>,
+ {
+ self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default);
+
+ self
+ }
+
+ fn get_filter(&self) -> Option<String> {
+ self.filter.get()
+ }
+
+ /// Specify an environment variable to read the style from.
+ pub fn write_style<E>(mut self, write_style_env: E) -> Self
+ where
+ E: Into<Cow<'a, str>>,
+ {
+ self.write_style = Var::new(write_style_env);
+
+ self
+ }
+
+ /// Specify an environment variable to read the style from.
+ ///
+ /// If the variable is not set, the default value will be used.
+ pub fn write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self
+ where
+ E: Into<Cow<'a, str>>,
+ V: Into<Cow<'a, str>>,
+ {
+ self.write_style = Var::new_with_default(write_style_env, default);
+
+ self
+ }
+
+ /// Use the default environment variable to read the style from.
+ ///
+ /// If the variable is not set, the default value will be used.
+ pub fn default_write_style_or<V>(mut self, default: V) -> Self
+ where
+ V: Into<Cow<'a, str>>,
+ {
+ self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default);
+
+ self
+ }
+
+ fn get_write_style(&self) -> Option<String> {
+ self.write_style.get()
+ }
+}
+
+impl<'a> Var<'a> {
+ fn new<E>(name: E) -> Self
+ where
+ E: Into<Cow<'a, str>>,
+ {
+ Var {
+ name: name.into(),
+ default: None,
+ }
+ }
+
+ fn new_with_default<E, V>(name: E, default: V) -> Self
+ where
+ E: Into<Cow<'a, str>>,
+ V: Into<Cow<'a, str>>,
+ {
+ Var {
+ name: name.into(),
+ default: Some(default.into()),
+ }
+ }
+
+ fn get(&self) -> Option<String> {
+ env::var(&*self.name)
+ .ok()
+ .or_else(|| self.default.to_owned().map(|v| v.into_owned()))
+ }
+}
+
+impl<'a, T> From<T> for Env<'a>
+where
+ T: Into<Cow<'a, str>>,
+{
+ fn from(filter_env: T) -> Self {
+ Env::default().filter(filter_env.into())
+ }
+}
+
+impl<'a> Default for Env<'a> {
+ fn default() -> Self {
+ Env {
+ filter: Var::new(DEFAULT_FILTER_ENV),
+ write_style: Var::new(DEFAULT_WRITE_STYLE_ENV),
+ }
+ }
+}
+
+mod std_fmt_impls {
+ use super::*;
+ use std::fmt;
+
+ impl fmt::Debug for Logger {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Logger")
+ .field("filter", &self.filter)
+ .finish()
+ }
+ }
+
+ impl fmt::Debug for Builder {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ if self.built {
+ f.debug_struct("Logger").field("built", &true).finish()
+ } else {
+ f.debug_struct("Logger")
+ .field("filter", &self.filter)
+ .field("writer", &self.writer)
+ .finish()
+ }
+ }
+ }
+}
+
+/// Attempts to initialize the global logger with an env logger.
+///
+/// This should be called early in the execution of a Rust program. Any log
+/// events that occur before initialization will be ignored.
+///
+/// # Errors
+///
+/// This function will fail if it is called more than once, or if another
+/// library has already initialized a global logger.
+pub fn try_init() -> Result<(), SetLoggerError> {
+ try_init_from_env(Env::default())
+}
+
+/// Initializes the global logger with an env logger.
+///
+/// This should be called early in the execution of a Rust program. Any log
+/// events that occur before initialization will be ignored.
+///
+/// # Panics
+///
+/// This function will panic if it is called more than once, or if another
+/// library has already initialized a global logger.
+pub fn init() {
+ try_init().expect("env_logger::init should not be called after logger initialized");
+}
+
+/// Attempts to initialize the global logger with an env logger from the given
+/// environment variables.
+///
+/// This should be called early in the execution of a Rust program. Any log
+/// events that occur before initialization will be ignored.
+///
+/// # Examples
+///
+/// Initialise a logger using the `MY_LOG` environment variable for filters
+/// and `MY_LOG_STYLE` for writing colors:
+///
+/// ```
+/// # extern crate env_logger;
+/// use env_logger::{Builder, Env};
+///
+/// # fn run() -> Result<(), Box<::std::error::Error>> {
+/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
+///
+/// env_logger::try_init_from_env(env)?;
+///
+/// Ok(())
+/// # }
+/// # fn main() { run().unwrap(); }
+/// ```
+///
+/// # Errors
+///
+/// This function will fail if it is called more than once, or if another
+/// library has already initialized a global logger.
+pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError>
+where
+ E: Into<Env<'a>>,
+{
+ let mut builder = Builder::from_env(env);
+
+ builder.try_init()
+}
+
+/// Initializes the global logger with an env logger from the given environment
+/// variables.
+///
+/// This should be called early in the execution of a Rust program. Any log
+/// events that occur before initialization will be ignored.
+///
+/// # Examples
+///
+/// Initialise a logger using the `MY_LOG` environment variable for filters
+/// and `MY_LOG_STYLE` for writing colors:
+///
+/// ```
+/// use env_logger::{Builder, Env};
+///
+/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
+///
+/// env_logger::init_from_env(env);
+/// ```
+///
+/// # Panics
+///
+/// This function will panic if it is called more than once, or if another
+/// library has already initialized a global logger.
+pub fn init_from_env<'a, E>(env: E)
+where
+ E: Into<Env<'a>>,
+{
+ try_init_from_env(env)
+ .expect("env_logger::init_from_env should not be called after logger initialized");
+}
+
+/// Create a new builder with the default environment variables.
+///
+/// The builder can be configured before being initialized.
+pub fn builder() -> Builder {
+ Builder::from_default_env()
+}
+
+/// Create a builder from the given environment variables.
+///
+/// The builder can be configured before being initialized.
+pub fn from_env<'a, E>(env: E) -> Builder
+where
+ E: Into<Env<'a>>,
+{
+ Builder::from_env(env)
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn env_get_filter_reads_from_var_if_set() {
+ env::set_var("env_get_filter_reads_from_var_if_set", "from var");
+
+ let env = Env::new().filter_or("env_get_filter_reads_from_var_if_set", "from default");
+
+ assert_eq!(Some("from var".to_owned()), env.get_filter());
+ }
+
+ #[test]
+ fn env_get_filter_reads_from_default_if_var_not_set() {
+ env::remove_var("env_get_filter_reads_from_default_if_var_not_set");
+
+ let env = Env::new().filter_or(
+ "env_get_filter_reads_from_default_if_var_not_set",
+ "from default",
+ );
+
+ assert_eq!(Some("from default".to_owned()), env.get_filter());
+ }
+
+ #[test]
+ fn env_get_write_style_reads_from_var_if_set() {
+ env::set_var("env_get_write_style_reads_from_var_if_set", "from var");
+
+ let env =
+ Env::new().write_style_or("env_get_write_style_reads_from_var_if_set", "from default");
+
+ assert_eq!(Some("from var".to_owned()), env.get_write_style());
+ }
+
+ #[test]
+ fn env_get_write_style_reads_from_default_if_var_not_set() {
+ env::remove_var("env_get_write_style_reads_from_default_if_var_not_set");
+
+ let env = Env::new().write_style_or(
+ "env_get_write_style_reads_from_default_if_var_not_set",
+ "from default",
+ );
+
+ assert_eq!(Some("from default".to_owned()), env.get_write_style());
+ }
+}
diff --git a/vendor/env_logger-0.7.1/tests/init-twice-retains-filter.rs b/vendor/env_logger-0.7.1/tests/init-twice-retains-filter.rs
new file mode 100644
index 000000000..673da3fd2
--- /dev/null
+++ b/vendor/env_logger-0.7.1/tests/init-twice-retains-filter.rs
@@ -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);
+}
diff --git a/vendor/env_logger-0.7.1/tests/log-in-log.rs b/vendor/env_logger-0.7.1/tests/log-in-log.rs
new file mode 100644
index 000000000..89517ff36
--- /dev/null
+++ b/vendor/env_logger-0.7.1/tests/log-in-log.rs
@@ -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);
+}
diff --git a/vendor/env_logger-0.7.1/tests/log_tls_dtors.rs b/vendor/env_logger-0.7.1/tests/log_tls_dtors.rs
new file mode 100644
index 000000000..5db87bd6c
--- /dev/null
+++ b/vendor/env_logger-0.7.1/tests/log_tls_dtors.rs
@@ -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);
+ }
+ }
+}
diff --git a/vendor/env_logger-0.7.1/tests/regexp_filter.rs b/vendor/env_logger-0.7.1/tests/regexp_filter.rs
new file mode 100644
index 000000000..40178bac7
--- /dev/null
+++ b/vendor/env_logger-0.7.1/tests/regexp_filter.rs
@@ -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");
+}