diff --git a/.cargo/config.in b/.cargo/config.in index 05f5433c69ec..2898d98319c3 100644 --- a/.cargo/config.in +++ b/.cargo/config.in @@ -15,7 +15,7 @@ tag = "v0.4.16" [source."https://github.com/mozilla/mp4parse-rust"] git = "https://github.com/mozilla/mp4parse-rust" replace-with = "vendored-sources" -rev = "94fd2f16b1a569a35801c4e7d858c6e1b24020ff" +rev = "f7c35a30ff25521bebe64c19d3f306569ecb5385" [source."https://github.com/mozilla/application-services"] git = "https://github.com/mozilla/application-services" diff --git a/Cargo.lock b/Cargo.lock index da26d58e8a66..0736a28e1403 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -217,7 +217,7 @@ dependencies = [ "bindgen", "cranelift-codegen", "cranelift-wasm", - "env_logger 0.8.2", + "env_logger", "log", "smallvec", ] @@ -1276,19 +1276,6 @@ dependencies = [ "packed_simd", ] -[[package]] -name = "env_logger" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -dependencies = [ - "atty", - "humantime 1.3.0", - "log", - "regex", - "termcolor", -] - [[package]] name = "env_logger" version = "0.8.2" @@ -1296,7 +1283,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26ecb66b4bdca6c1409b40fb255eefc2bd4f6d135dab3c3124f80ffa2a9661e" dependencies = [ "atty", - "humantime 2.0.1", + "humantime", "log", "regex", "termcolor", @@ -1373,9 +1360,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fallible_collections" -version = "0.3.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9599e8ccc571becb62700174680e54e5c50fc5b4d34c1c56d8915e0325650fea" +checksum = "3bda4d04bca84e2331f0ff2ee8300064df3f467e37743d87788c1487a6dd903b" dependencies = [ "hashbrown", ] @@ -1734,7 +1721,7 @@ name = "gecko_logger" version = "0.1.0" dependencies = [ "app_services_logger", - "env_logger 0.8.2", + "env_logger", "lazy_static", "log", ] @@ -2328,15 +2315,6 @@ version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" -[[package]] -name = "humantime" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error", -] - [[package]] name = "humantime" version = "2.0.1" @@ -2522,7 +2500,7 @@ version = "0.1.4" dependencies = [ "bindgen", "cmake", - "env_logger 0.8.2", + "env_logger", "glob", "lazy_static", "libc", @@ -3257,11 +3235,10 @@ dependencies = [ [[package]] name = "mp4parse" version = "0.11.4" -source = "git+https://github.com/mozilla/mp4parse-rust?rev=94fd2f16b1a569a35801c4e7d858c6e1b24020ff#94fd2f16b1a569a35801c4e7d858c6e1b24020ff" +source = "git+https://github.com/mozilla/mp4parse-rust?rev=f7c35a30ff25521bebe64c19d3f306569ecb5385#f7c35a30ff25521bebe64c19d3f306569ecb5385" dependencies = [ "bitreader", "byteorder", - "env_logger 0.7.1", "fallible_collections", "hashbrown", "log", @@ -3276,7 +3253,7 @@ version = "0.1.0" [[package]] name = "mp4parse_capi" version = "0.11.4" -source = "git+https://github.com/mozilla/mp4parse-rust?rev=94fd2f16b1a569a35801c4e7d858c6e1b24020ff#94fd2f16b1a569a35801c4e7d858c6e1b24020ff" +source = "git+https://github.com/mozilla/mp4parse-rust?rev=f7c35a30ff25521bebe64c19d3f306569ecb5385#f7c35a30ff25521bebe64c19d3f306569ecb5385" dependencies = [ "byteorder", "fallible_collections", @@ -3321,7 +3298,7 @@ version = "0.4.16" source = "git+https://github.com/mozilla/neqo?tag=v0.4.16#1b0664a1e2b3ac59a5c919d32ddc284dc57634e6" dependencies = [ "chrono", - "env_logger 0.8.2", + "env_logger", "lazy_static", "log", "qlog", @@ -3637,7 +3614,7 @@ version = "0.1.4" dependencies = [ "byteorder", "core-foundation", - "env_logger 0.8.2", + "env_logger", "lazy_static", "libloading 0.5.2", "log", @@ -3885,7 +3862,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50ce7c785e06e3a9e6f546c1a30d3d59111a31a21bc294fb1496241a572c9a00" dependencies = [ "base64 0.10.1", - "humantime 2.0.1", + "humantime", "indexmap", "line-wrap", "serde", @@ -4719,7 +4696,7 @@ name = "smoosh" version = "0.1.0" dependencies = [ "bumpalo", - "env_logger 0.8.2", + "env_logger", "jsparagus", "log", ] @@ -4919,7 +4896,7 @@ dependencies = [ "atomic_refcell", "cssparser", "cstr", - "env_logger 0.8.2", + "env_logger", "geckoservo", "libc", "log", diff --git a/image/decoders/nsAVIFDecoder.cpp b/image/decoders/nsAVIFDecoder.cpp index 73982a61c066..0d47c237dcfa 100644 --- a/image/decoders/nsAVIFDecoder.cpp +++ b/image/decoders/nsAVIFDecoder.cpp @@ -507,24 +507,23 @@ nsAVIFDecoder::DecodeResult nsAVIFDecoder::Decode( return AsVariant(NonDecoderResult::ParseError); } - AvifImage image = {}; - Mp4parseStatus status = mp4parse_avif_get_image(mParser, &image); + Mp4parseByteData primaryItem = {}; + Mp4parseStatus status = mp4parse_avif_get_primary_item(mParser, &primaryItem); MOZ_LOG(sAVIFLog, LogLevel::Debug, ("[this=%p] mp4parse_avif_get_primary_item -> %d; length: %u", this, - status, image.primary_item.length)); + status, primaryItem.length)); - if (status != MP4PARSE_STATUS_OK || !image.primary_item.data || - !image.primary_item.length) { + if (status != MP4PARSE_STATUS_OK) { return AsVariant(NonDecoderResult::NoPrimaryItem); } layers::PlanarYCbCrData decodedData; DecodeResult decodeResult = AsVariant(NonDecoderResult::MetadataOk); if (StaticPrefs::image_avif_use_dav1d()) { - decodeResult = AsVariant(DecodeWithDav1d(image.primary_item, decodedData)); + decodeResult = AsVariant(DecodeWithDav1d(primaryItem, decodedData)); } else { - decodeResult = AsVariant(DecodeWithAOM(image.primary_item, decodedData)); + decodeResult = AsVariant(DecodeWithAOM(primaryItem, decodedData)); } bool decodeOK = IsDecodeSuccess(decodeResult); MOZ_LOG(sAVIFLog, LogLevel::Debug, diff --git a/third_party/rust/env_logger-0.7.1/.cargo-checksum.json b/third_party/rust/env_logger-0.7.1/.cargo-checksum.json deleted file mode 100644 index f7fcd9e6bc23..000000000000 --- a/third_party/rust/env_logger-0.7.1/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"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/third_party/rust/env_logger-0.7.1/CHANGELOG.md b/third_party/rust/env_logger-0.7.1/CHANGELOG.md deleted file mode 100644 index f849eefff6eb..000000000000 --- a/third_party/rust/env_logger-0.7.1/CHANGELOG.md +++ /dev/null @@ -1,3 +0,0 @@ -Changes to this crate are tracked via [GitHub Releases][releases]. - -[releases]: https://github.com/sebasmagri/env_logger/releases diff --git a/third_party/rust/env_logger-0.7.1/Cargo.lock b/third_party/rust/env_logger-0.7.1/Cargo.lock deleted file mode 100644 index bf04607aae65..000000000000 --- a/third_party/rust/env_logger-0.7.1/Cargo.lock +++ /dev/null @@ -1,212 +0,0 @@ -# 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/third_party/rust/env_logger-0.7.1/Cargo.toml b/third_party/rust/env_logger-0.7.1/Cargo.toml deleted file mode 100644 index c34a1ee2391d..000000000000 --- a/third_party/rust/env_logger-0.7.1/Cargo.toml +++ /dev/null @@ -1,62 +0,0 @@ -# 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/third_party/rust/env_logger-0.7.1/LICENSE-APACHE b/third_party/rust/env_logger-0.7.1/LICENSE-APACHE deleted file mode 100644 index 16fe87b06e80..000000000000 --- a/third_party/rust/env_logger-0.7.1/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - 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/third_party/rust/env_logger-0.7.1/LICENSE-MIT b/third_party/rust/env_logger-0.7.1/LICENSE-MIT deleted file mode 100644 index 39d4bdb5acd3..000000000000 --- a/third_party/rust/env_logger-0.7.1/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -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/third_party/rust/env_logger-0.7.1/README.md b/third_party/rust/env_logger-0.7.1/README.md deleted file mode 100644 index 34e4194a88fb..000000000000 --- a/third_party/rust/env_logger-0.7.1/README.md +++ /dev/null @@ -1,150 +0,0 @@ -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/third_party/rust/env_logger-0.7.1/examples/custom_default_format.rs b/third_party/rust/env_logger-0.7.1/examples/custom_default_format.rs deleted file mode 100644 index 43979247ca5b..000000000000 --- a/third_party/rust/env_logger-0.7.1/examples/custom_default_format.rs +++ /dev/null @@ -1,41 +0,0 @@ -/*! -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/third_party/rust/env_logger-0.7.1/examples/custom_format.rs b/third_party/rust/env_logger-0.7.1/examples/custom_format.rs deleted file mode 100644 index df5a8e5b9cd9..000000000000 --- a/third_party/rust/env_logger-0.7.1/examples/custom_format.rs +++ /dev/null @@ -1,53 +0,0 @@ -/*! -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/third_party/rust/env_logger-0.7.1/examples/custom_logger.rs b/third_party/rust/env_logger-0.7.1/examples/custom_logger.rs deleted file mode 100644 index 85de45b2d97d..000000000000 --- a/third_party/rust/env_logger-0.7.1/examples/custom_logger.rs +++ /dev/null @@ -1,60 +0,0 @@ -/*! -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/third_party/rust/env_logger-0.7.1/examples/default.rs b/third_party/rust/env_logger-0.7.1/examples/default.rs deleted file mode 100644 index 67bb030745e7..000000000000 --- a/third_party/rust/env_logger-0.7.1/examples/default.rs +++ /dev/null @@ -1,38 +0,0 @@ -/*! -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/third_party/rust/env_logger-0.7.1/examples/direct_logger.rs b/third_party/rust/env_logger-0.7.1/examples/direct_logger.rs deleted file mode 100644 index 4ba023fae3bc..000000000000 --- a/third_party/rust/env_logger-0.7.1/examples/direct_logger.rs +++ /dev/null @@ -1,37 +0,0 @@ -/*! -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/third_party/rust/env_logger-0.7.1/examples/filters_from_code.rs b/third_party/rust/env_logger-0.7.1/examples/filters_from_code.rs deleted file mode 100644 index 4137c91898b0..000000000000 --- a/third_party/rust/env_logger-0.7.1/examples/filters_from_code.rs +++ /dev/null @@ -1,18 +0,0 @@ -/*! -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/third_party/rust/env_logger-0.7.1/src/filter/mod.rs b/third_party/rust/env_logger-0.7.1/src/filter/mod.rs deleted file mode 100644 index a994f4dc6cd6..000000000000 --- a/third_party/rust/env_logger-0.7.1/src/filter/mod.rs +++ /dev/null @@ -1,616 +0,0 @@ -//! 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, - filter: Option, -} - -/// 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, - filter: Option, - built: bool, -} - -#[derive(Debug)] -struct Directive { - name: Option, - 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, Option) { - 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) -> 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/third_party/rust/env_logger-0.7.1/src/filter/regex.rs b/third_party/rust/env_logger-0.7.1/src/filter/regex.rs deleted file mode 100644 index fb21528a1216..000000000000 --- a/third_party/rust/env_logger-0.7.1/src/filter/regex.rs +++ /dev/null @@ -1,29 +0,0 @@ -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 { - 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/third_party/rust/env_logger-0.7.1/src/filter/string.rs b/third_party/rust/env_logger-0.7.1/src/filter/string.rs deleted file mode 100644 index ea476e42f934..000000000000 --- a/third_party/rust/env_logger-0.7.1/src/filter/string.rs +++ /dev/null @@ -1,24 +0,0 @@ -use std::fmt; - -#[derive(Debug)] -pub struct Filter { - inner: String, -} - -impl Filter { - pub fn new(spec: &str) -> Result { - 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/third_party/rust/env_logger-0.7.1/src/fmt/humantime/extern_impl.rs b/third_party/rust/env_logger-0.7.1/src/fmt/humantime/extern_impl.rs deleted file mode 100644 index 19dec1b65d39..000000000000 --- a/third_party/rust/env_logger-0.7.1/src/fmt/humantime/extern_impl.rs +++ /dev/null @@ -1,118 +0,0 @@ -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/third_party/rust/env_logger-0.7.1/src/fmt/humantime/mod.rs b/third_party/rust/env_logger-0.7.1/src/fmt/humantime/mod.rs deleted file mode 100644 index ac23ae2493f3..000000000000 --- a/third_party/rust/env_logger-0.7.1/src/fmt/humantime/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -/* -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/third_party/rust/env_logger-0.7.1/src/fmt/humantime/shim_impl.rs b/third_party/rust/env_logger-0.7.1/src/fmt/humantime/shim_impl.rs deleted file mode 100644 index 906bf9e4c1a6..000000000000 --- a/third_party/rust/env_logger-0.7.1/src/fmt/humantime/shim_impl.rs +++ /dev/null @@ -1,5 +0,0 @@ -/* -Timestamps aren't available when we don't have a `humantime` dependency. -*/ - -pub(in crate::fmt) mod glob {} diff --git a/third_party/rust/env_logger-0.7.1/src/fmt/mod.rs b/third_party/rust/env_logger-0.7.1/src/fmt/mod.rs deleted file mode 100644 index e699e214d64b..000000000000 --- a/third_party/rust/env_logger-0.7.1/src/fmt/mod.rs +++ /dev/null @@ -1,489 +0,0 @@ -//! 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>, - 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 { - 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, - pub format_module_path: bool, - pub format_level: bool, - pub format_indent: Option, - #[allow(unknown_lints, bare_trait_objects)] - pub custom_format: Option 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 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, - module_path: bool, - level: bool, - written_header_value: bool, - indent: Option, - 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(&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 { - 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/third_party/rust/env_logger-0.7.1/src/fmt/writer/atty.rs b/third_party/rust/env_logger-0.7.1/src/fmt/writer/atty.rs deleted file mode 100644 index f6718413f0d6..000000000000 --- a/third_party/rust/env_logger-0.7.1/src/fmt/writer/atty.rs +++ /dev/null @@ -1,34 +0,0 @@ -/* -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/third_party/rust/env_logger-0.7.1/src/fmt/writer/mod.rs b/third_party/rust/env_logger-0.7.1/src/fmt/writer/mod.rs deleted file mode 100644 index 6ee63a39811c..000000000000 --- a/third_party/rust/env_logger-0.7.1/src/fmt/writer/mod.rs +++ /dev/null @@ -1,201 +0,0 @@ -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/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/extern_impl.rs b/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/extern_impl.rs deleted file mode 100644 index 2d38e375aaf4..000000000000 --- a/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/extern_impl.rs +++ /dev/null @@ -1,486 +0,0 @@ -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, -} - -pub(in crate::fmt) struct Buffer { - inner: termcolor::Buffer, - test_target: Option, -} - -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 { - 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>, - 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(&self, value: T) -> StyledValue { - StyledValue { - style: Cow::Borrowed(self), - value, - } - } - - /// Wrap a value in the style by taking ownership of it. - pub(crate) fn into_value(&mut self, value: T) -> StyledValue<'static, T> { - StyledValue { - style: Cow::Owned(self.clone()), - value, - } - } -} - -impl<'a, T> StyledValue<'a, T> { - fn write_fmt(&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 { - 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/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/mod.rs b/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/mod.rs deleted file mode 100644 index f3e6768cd051..000000000000 --- a/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -/* -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/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/shim_impl.rs b/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/shim_impl.rs deleted file mode 100644 index 563f8ad4ffd7..000000000000 --- a/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/shim_impl.rs +++ /dev/null @@ -1,63 +0,0 @@ -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); - -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 { - 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/third_party/rust/env_logger-0.7.1/src/lib.rs b/third_party/rust/env_logger-0.7.1/src/lib.rs deleted file mode 100644 index 415183600b26..000000000000 --- a/third_party/rust/env_logger-0.7.1/src/lib.rs +++ /dev/null @@ -1,1177 +0,0 @@ -// 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 or the MIT license -// , 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>, -} - -/// 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 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>, - { - 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(&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) -> &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) -> &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>, - { - 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> = 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(mut self, filter_env: E) -> Self - where - E: Into>, - { - 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(mut self, filter_env: E, default: V) -> Self - where - E: Into>, - V: Into>, - { - 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(mut self, default: V) -> Self - where - V: Into>, - { - self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default); - - self - } - - fn get_filter(&self) -> Option { - self.filter.get() - } - - /// Specify an environment variable to read the style from. - pub fn write_style(mut self, write_style_env: E) -> Self - where - E: Into>, - { - 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(mut self, write_style_env: E, default: V) -> Self - where - E: Into>, - V: Into>, - { - 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(mut self, default: V) -> Self - where - V: Into>, - { - self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default); - - self - } - - fn get_write_style(&self) -> Option { - self.write_style.get() - } -} - -impl<'a> Var<'a> { - fn new(name: E) -> Self - where - E: Into>, - { - Var { - name: name.into(), - default: None, - } - } - - fn new_with_default(name: E, default: V) -> Self - where - E: Into>, - V: Into>, - { - Var { - name: name.into(), - default: Some(default.into()), - } - } - - fn get(&self) -> Option { - env::var(&*self.name) - .ok() - .or_else(|| self.default.to_owned().map(|v| v.into_owned())) - } -} - -impl<'a, T> From for Env<'a> -where - T: Into>, -{ - 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>, -{ - 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>, -{ - 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>, -{ - 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/third_party/rust/env_logger-0.7.1/tests/init-twice-retains-filter.rs b/third_party/rust/env_logger-0.7.1/tests/init-twice-retains-filter.rs deleted file mode 100644 index 673da3fd2879..000000000000 --- a/third_party/rust/env_logger-0.7.1/tests/init-twice-retains-filter.rs +++ /dev/null @@ -1,40 +0,0 @@ -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/third_party/rust/env_logger-0.7.1/tests/log-in-log.rs b/third_party/rust/env_logger-0.7.1/tests/log-in-log.rs deleted file mode 100644 index 89517ff36236..000000000000 --- a/third_party/rust/env_logger-0.7.1/tests/log-in-log.rs +++ /dev/null @@ -1,39 +0,0 @@ -#[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/third_party/rust/env_logger-0.7.1/tests/log_tls_dtors.rs b/third_party/rust/env_logger-0.7.1/tests/log_tls_dtors.rs deleted file mode 100644 index 5db87bd6c59a..000000000000 --- a/third_party/rust/env_logger-0.7.1/tests/log_tls_dtors.rs +++ /dev/null @@ -1,66 +0,0 @@ -#[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/third_party/rust/env_logger-0.7.1/tests/regexp_filter.rs b/third_party/rust/env_logger-0.7.1/tests/regexp_filter.rs deleted file mode 100644 index 40178bac7fdc..000000000000 --- a/third_party/rust/env_logger-0.7.1/tests/regexp_filter.rs +++ /dev/null @@ -1,57 +0,0 @@ -#[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"); -} diff --git a/third_party/rust/fallible_collections/.cargo-checksum.json b/third_party/rust/fallible_collections/.cargo-checksum.json index 8f465a5eba09..c05eb18a6ad9 100644 --- a/third_party/rust/fallible_collections/.cargo-checksum.json +++ b/third_party/rust/fallible_collections/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"9be745f2a777ab28fdaccf77169f89aad4eb28fee0513628312a00d5e4561c06","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"d05831c6d3375eb1fcb35183ab4ff3fa7b5819068b728a49af3102f5f8fdf7e0","src/arc.rs":"60742619b7404d8c46237e9a3f98c49f75f88e4c24513ebca1d0ddad0274b6d6","src/boxed.rs":"40537576912a01ed8bb3bd6b1c8179632613f37f65459e708d4abc2286933c57","src/btree.rs":"b83820fc2a00e2e34127b3037abde8b945f0ca2785f3def725787e6813c3d3e0","src/btree/map.rs":"4d8710cf6f00bd889045a6144de692d9f752d51089db493e859d55e5ba12430a","src/btree/node.rs":"f6b4557d30ca0e30c7c7b6752c7a2c67432aab5c18c08392a28040326620a109","src/btree/search.rs":"ae78f73f3e56ea277b0a02cc39454447b75e12a6c817ecfee00065b3ddbfff67","src/btree/set.rs":"29cc3bff736007b21e14017d880edbcc7c76c30e0c256e811cae1fff0dad13fa","src/format.rs":"cee32d75cf260b19c8db74b50852bc50b8c47189d22b7424b647d084c4a76857","src/hashmap.rs":"d64ce1acfb3a4ea3e1f0130f5bcf6a3064fce01a0055e0f29163034adaa14173","src/lib.rs":"4cd0ef055208600292ec075f600e940eafcd24bd3e74fe34bba9164842d7f380","src/rc.rs":"102ad49f2201b9f69b50cf5a35af1e0039094936354b12572702551970c2f53c","src/try_clone.rs":"32c790435c71dec116756c284d2b953d382292b7727675740229a6b53d8c8b41","src/vec.rs":"f5170e48333803a49d74b670eb48917c77613d3df97ba8bbfb75340d59898ace"},"package":"9599e8ccc571becb62700174680e54e5c50fc5b4d34c1c56d8915e0325650fea"} \ No newline at end of file +{"files":{"Cargo.toml":"2a7958c74d86b964737863c4d869cb8e7ae64ec85632600fd7cef6e87ee0be47","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"6d74a8ddac747e9fd6d8c2000c6d0ae05bc28bb9e47e629e86d4b8d05115f546","src/arc.rs":"60742619b7404d8c46237e9a3f98c49f75f88e4c24513ebca1d0ddad0274b6d6","src/boxed.rs":"40537576912a01ed8bb3bd6b1c8179632613f37f65459e708d4abc2286933c57","src/btree.rs":"b83820fc2a00e2e34127b3037abde8b945f0ca2785f3def725787e6813c3d3e0","src/btree/map.rs":"4d8710cf6f00bd889045a6144de692d9f752d51089db493e859d55e5ba12430a","src/btree/node.rs":"f6b4557d30ca0e30c7c7b6752c7a2c67432aab5c18c08392a28040326620a109","src/btree/search.rs":"ae78f73f3e56ea277b0a02cc39454447b75e12a6c817ecfee00065b3ddbfff67","src/btree/set.rs":"29cc3bff736007b21e14017d880edbcc7c76c30e0c256e811cae1fff0dad13fa","src/format.rs":"cee32d75cf260b19c8db74b50852bc50b8c47189d22b7424b647d084c4a76857","src/hashmap.rs":"cf02762085d9968fc235ef2c0626358661cb21aca2c8c19961b3969225c96dce","src/lib.rs":"4cd0ef055208600292ec075f600e940eafcd24bd3e74fe34bba9164842d7f380","src/rc.rs":"102ad49f2201b9f69b50cf5a35af1e0039094936354b12572702551970c2f53c","src/try_clone.rs":"32c790435c71dec116756c284d2b953d382292b7727675740229a6b53d8c8b41","src/vec.rs":"691e80f89ffd25ea3e0cb287ea9bdecb1528367f21a8b3d995e9b3915c01c8e4"},"package":"3bda4d04bca84e2331f0ff2ee8300064df3f467e37743d87788c1487a6dd903b"} \ No newline at end of file diff --git a/third_party/rust/fallible_collections/Cargo.toml b/third_party/rust/fallible_collections/Cargo.toml index 2320f89f1669..9639ba647031 100644 --- a/third_party/rust/fallible_collections/Cargo.toml +++ b/third_party/rust/fallible_collections/Cargo.toml @@ -13,7 +13,7 @@ [package] edition = "2018" name = "fallible_collections" -version = "0.3.1" +version = "0.2.0" authors = ["vcombey "] description = "a crate which adds fallible allocation api to std collections" readme = "README.md" diff --git a/third_party/rust/fallible_collections/README.md b/third_party/rust/fallible_collections/README.md index cda9e0bca0df..860f94d66c29 100644 --- a/third_party/rust/fallible_collections/README.md +++ b/third_party/rust/fallible_collections/README.md @@ -20,7 +20,7 @@ Add the following dependency to your Cargo manifest... ```toml [dependencies] -fallible_collections = "0.3.1" +fallible_collections = "0.1.3" ``` ...and see the [docs](https://docs.rs/fallible_collections) for how to use it. diff --git a/third_party/rust/fallible_collections/src/hashmap.rs b/third_party/rust/fallible_collections/src/hashmap.rs index 3d063613a8ec..3c53f4e30d1c 100644 --- a/third_party/rust/fallible_collections/src/hashmap.rs +++ b/third_party/rust/fallible_collections/src/hashmap.rs @@ -1,7 +1,6 @@ //! Implement Fallible HashMap use super::TryClone; use crate::TryReserveError; -use core::borrow::Borrow; use core::default::Default; use core::hash::Hash; @@ -26,7 +25,7 @@ where pub fn get(&self, k: &Q) -> Option<&V> where - K: Borrow, + K: core::borrow::Borrow, Q: Hash + Eq, { self.inner.get(k) @@ -37,36 +36,11 @@ where Ok(self.inner.insert(k, v)) } - pub fn iter(&self) -> hashbrown::hash_map::Iter<'_, K, V> { - self.inner.iter() - } - - pub fn len(&self) -> usize { - self.inner.len() - } - - pub fn remove(&mut self, k: &Q) -> Option - where - K: Borrow, - Q: Hash + Eq, - { - self.inner.remove(k) - } - fn reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.inner.try_reserve(additional) } } -impl IntoIterator for TryHashMap { - type Item = (K, V); - type IntoIter = hashbrown::hash_map::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.inner.into_iter() - } -} - impl TryClone for TryHashMap where K: Eq + Hash + TryClone, diff --git a/third_party/rust/fallible_collections/src/vec.rs b/third_party/rust/fallible_collections/src/vec.rs index 954c45df9d4b..ee4d532b0607 100644 --- a/third_party/rust/fallible_collections/src/vec.rs +++ b/third_party/rust/fallible_collections/src/vec.rs @@ -64,19 +64,11 @@ pub trait FallibleVec { /// fallible allocation. /// /// See the crate documentation for more. -#[derive(PartialEq)] +#[derive(Default, PartialEq)] pub struct TryVec { inner: Vec, } -impl Default for TryVec { - fn default() -> Self { - Self { - inner: Default::default(), - } - } -} - impl core::fmt::Debug for TryVec { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{:?}", self.inner) diff --git a/third_party/rust/humantime-1.3.0/.cargo-checksum.json b/third_party/rust/humantime-1.3.0/.cargo-checksum.json deleted file mode 100644 index 2ffd8f042d50..000000000000 --- a/third_party/rust/humantime-1.3.0/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"ae7f884d13f5d849afd58b5db15510396832df7f648b0095e43bfdfa600b2ba3","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"f6deca8261a8f4a3403dc74c725c46051157fd36c27cd4b100277eb1f303ad11","README.md":"e4bb65f28ddffb11d7eb337e9585947651f2fc11a5e4290f0ca126e21c582c1e","benches/datetime_format.rs":"a44c7ffb3c9515e92828564df8f91a86470343a2fa7e1a08bc2bc7397ba2591c","benches/datetime_parse.rs":"336a241755ccfa546d1840e56a40218c4f98f22d7d274829c5102ec280f2d963","bulk.yaml":"17c2548388e0cd3a63473021a2f1e4ddedee082d79d9167cb31ad06a1890d3fc","src/date.rs":"ea9924869a2484e333df2a845009593dd0062bb3b3e1a5ef9cefc05ec0a41196","src/duration.rs":"a5d4756451f495a3d5df0c872caa6304dd81ae075f0e204c8145c11c7c8f698b","src/lib.rs":"59dcc8a1ed89ecde199d59a7f71e550b461f87858b4becffb0a183994bafdd7c","src/wrapper.rs":"5bbdaf43256b445a8ca3a6b3eded9dd4fa8fb4dadf3683a5bac9648d91117396","vagga.yaml":"59761e5138a3015ef5654fec095ac8f1587cd23529b37822dd540b866fe4cd5b"},"package":"df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"} \ No newline at end of file diff --git a/third_party/rust/humantime-1.3.0/Cargo.toml b/third_party/rust/humantime-1.3.0/Cargo.toml deleted file mode 100644 index 53bdcfd2cf7e..000000000000 --- a/third_party/rust/humantime-1.3.0/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -# 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] -name = "humantime" -version = "1.3.0" -authors = ["Paul Colomiets "] -description = " A parser and formatter for std::time::{Duration, SystemTime}\n" -homepage = "https://github.com/tailhook/humantime" -documentation = "https://docs.rs/humantime" -readme = "README.md" -keywords = ["time", "human", "human-friendly", "parser", "duration"] -categories = ["date-and-time"] -license = "MIT/Apache-2.0" - -[lib] -name = "humantime" -path = "src/lib.rs" -[dependencies.quick-error] -version = "1.0.0" -[dev-dependencies.chrono] -version = "0.4.0" - -[dev-dependencies.rand] -version = "0.4.2" - -[dev-dependencies.time] -version = "0.1.39" diff --git a/third_party/rust/humantime-1.3.0/LICENSE-APACHE b/third_party/rust/humantime-1.3.0/LICENSE-APACHE deleted file mode 100644 index 8f71f43fee3f..000000000000 --- a/third_party/rust/humantime-1.3.0/LICENSE-APACHE +++ /dev/null @@ -1,202 +0,0 @@ - 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/third_party/rust/humantime-1.3.0/LICENSE-MIT b/third_party/rust/humantime-1.3.0/LICENSE-MIT deleted file mode 100644 index a099fbade45d..000000000000 --- a/third_party/rust/humantime-1.3.0/LICENSE-MIT +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2016 The humantime Developers - -Includes parts of http date with the following copyright: -Copyright (c) 2016 Pyfisch - -Includes portions of musl libc with the following copyright: -Copyright © 2005-2013 Rich Felker - - -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/third_party/rust/humantime-1.3.0/README.md b/third_party/rust/humantime-1.3.0/README.md deleted file mode 100644 index 39156dcdc941..000000000000 --- a/third_party/rust/humantime-1.3.0/README.md +++ /dev/null @@ -1,68 +0,0 @@ -Human Time -========== - -**Status: stable** - -[Documentation](https://docs.rs/humantime) | -[Github](https://github.com/tailhook/humantime) | -[Crate](https://crates.io/crates/humantime) - - -Features: - -* Parses durations in free form like `15days 2min 2s` -* Formats durations in similar form `2years 2min 12us` -* Parses and formats timestamp in `rfc3339` format: `2018-01-01T12:53:00Z` -* Parses timestamps in a weaker format: `2018-01-01 12:53:00` - -Timestamp parsing/formatting is super-fast because format is basically -fixed. - -Here are some micro-benchmarks: - -``` -test result: ok. 0 passed; 0 failed; 26 ignored; 0 measured; 0 filtered out - - Running target/release/deps/datetime_format-8facb4ac832d9770 - -running 2 tests -test rfc3339_chrono ... bench: 737 ns/iter (+/- 37) -test rfc3339_humantime_seconds ... bench: 73 ns/iter (+/- 2) - -test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out - - Running target/release/deps/datetime_parse-342628f877d7867c - -running 6 tests -test datetime_utc_parse_millis ... bench: 228 ns/iter (+/- 11) -test datetime_utc_parse_nanos ... bench: 236 ns/iter (+/- 10) -test datetime_utc_parse_seconds ... bench: 204 ns/iter (+/- 18) -test rfc3339_humantime_millis ... bench: 28 ns/iter (+/- 1) -test rfc3339_humantime_nanos ... bench: 36 ns/iter (+/- 2) -test rfc3339_humantime_seconds ... bench: 24 ns/iter (+/- 1) - -test result: ok. 0 passed; 0 failed; 0 ignored; 6 measured; 0 filtered out -``` - -See [humantime-serde] for serde integration (previous crate [serde-humantime] looks unmaintained). - -[serde-humantime]: https://docs.rs/serde-humantime/0.1.1/serde_humantime/ -[humantime-serde]: https://docs.rs/humantime-serde - -License -======= - -Licensed under either of - -* Apache License, Version 2.0, (./LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) -* MIT license (./LICENSE-MIT or http://opensource.org/licenses/MIT) - -at your option. - -Contribution ------------- - -Unless you explicitly state otherwise, any contribution intentionally -submitted for inclusion in the work by you, as defined in the Apache-2.0 -license, shall be dual licensed as above, without any additional terms or -conditions. diff --git a/third_party/rust/humantime-1.3.0/benches/datetime_format.rs b/third_party/rust/humantime-1.3.0/benches/datetime_format.rs deleted file mode 100644 index 7f6dca79c58d..000000000000 --- a/third_party/rust/humantime-1.3.0/benches/datetime_format.rs +++ /dev/null @@ -1,58 +0,0 @@ -#![feature(test)] -extern crate chrono; -extern crate humantime; -extern crate test; - -use std::io::Write; -use std::time::{Duration, UNIX_EPOCH}; -use humantime::format_rfc3339; - - -#[bench] -fn rfc3339_humantime_seconds(b: &mut test::Bencher) { - let time = UNIX_EPOCH + Duration::new(1483228799, 0); - let mut buf = Vec::with_capacity(100); - b.iter(|| { - buf.truncate(0); - write!(&mut buf, "{}", format_rfc3339(time)).unwrap() - }); -} - -#[bench] -fn rfc3339_chrono(b: &mut test::Bencher) { - use chrono::{DateTime, NaiveDateTime, Utc}; - use chrono::format::Item; - use chrono::format::Item::*; - use chrono::format::Numeric::*; - use chrono::format::Fixed::*; - use chrono::format::Pad::*; - - let time = DateTime::::from_utc( - NaiveDateTime::from_timestamp(1483228799, 0), Utc); - let mut buf = Vec::with_capacity(100); - - // formatting code from env_logger - const ITEMS: &'static [Item<'static>] = { - &[ - Numeric(Year, Zero), - Literal("-"), - Numeric(Month, Zero), - Literal("-"), - Numeric(Day, Zero), - Literal("T"), - Numeric(Hour, Zero), - Literal(":"), - Numeric(Minute, Zero), - Literal(":"), - Numeric(Second, Zero), - Fixed(TimezoneOffsetZ), - ] - }; - - - b.iter(|| { - buf.truncate(0); - write!(&mut buf, "{}", time.format_with_items(ITEMS.iter().cloned())) - .unwrap() - }); -} diff --git a/third_party/rust/humantime-1.3.0/benches/datetime_parse.rs b/third_party/rust/humantime-1.3.0/benches/datetime_parse.rs deleted file mode 100644 index 785d713d3f5a..000000000000 --- a/third_party/rust/humantime-1.3.0/benches/datetime_parse.rs +++ /dev/null @@ -1,50 +0,0 @@ -#![feature(test)] -extern crate chrono; -extern crate humantime; -extern crate test; - -use chrono::{DateTime}; -use humantime::parse_rfc3339; - - -#[bench] -fn rfc3339_humantime_seconds(b: &mut test::Bencher) { - b.iter(|| { - parse_rfc3339("2018-02-13T23:08:32Z").unwrap() - }); -} - -#[bench] -fn datetime_utc_parse_seconds(b: &mut test::Bencher) { - b.iter(|| { - DateTime::parse_from_rfc3339("2018-02-13T23:08:32Z").unwrap() - }); -} - -#[bench] -fn rfc3339_humantime_millis(b: &mut test::Bencher) { - b.iter(|| { - parse_rfc3339("2018-02-13T23:08:32.123Z").unwrap() - }); -} - -#[bench] -fn datetime_utc_parse_millis(b: &mut test::Bencher) { - b.iter(|| { - DateTime::parse_from_rfc3339("2018-02-13T23:08:32.123Z").unwrap() - }); -} - -#[bench] -fn rfc3339_humantime_nanos(b: &mut test::Bencher) { - b.iter(|| { - parse_rfc3339("2018-02-13T23:08:32.123456983Z").unwrap() - }); -} - -#[bench] -fn datetime_utc_parse_nanos(b: &mut test::Bencher) { - b.iter(|| { - DateTime::parse_from_rfc3339("2018-02-13T23:08:32.123456983Z").unwrap() - }); -} diff --git a/third_party/rust/humantime-1.3.0/bulk.yaml b/third_party/rust/humantime-1.3.0/bulk.yaml deleted file mode 100644 index cdb9763b67d6..000000000000 --- a/third_party/rust/humantime-1.3.0/bulk.yaml +++ /dev/null @@ -1,8 +0,0 @@ -minimum-bulk: v0.4.5 - -versions: - -- file: Cargo.toml - block-start: ^\[package\] - block-end: ^\[.*\] - regex: ^version\s*=\s*"(\S+)" diff --git a/third_party/rust/humantime-1.3.0/src/date.rs b/third_party/rust/humantime-1.3.0/src/date.rs deleted file mode 100644 index d5bc82cf6c10..000000000000 --- a/third_party/rust/humantime-1.3.0/src/date.rs +++ /dev/null @@ -1,614 +0,0 @@ -use std::fmt; -use std::str; -use std::time::{SystemTime, Duration, UNIX_EPOCH}; - -#[cfg(target_os="cloudabi")] -mod max { - pub const SECONDS: u64 = ::std::u64::MAX / 1_000_000_000; - #[allow(unused)] - pub const TIMESTAMP: &'static str = "2554-07-21T23:34:33Z"; -} -#[cfg(all( - target_pointer_width="32", - not(target_os="cloudabi"), - not(target_os="windows"), - not(all(target_arch="wasm32", not(target_os="emscripten"))) -))] -mod max { - pub const SECONDS: u64 = ::std::i32::MAX as u64; - #[allow(unused)] - pub const TIMESTAMP: &'static str = "2038-01-19T03:14:07Z"; -} - -#[cfg(any( - target_pointer_width="64", - target_os="windows", - all(target_arch="wasm32", not(target_os="emscripten")), -))] -mod max { - pub const SECONDS: u64 = 253402300800-1; // last second of year 9999 - #[allow(unused)] - pub const TIMESTAMP: &'static str = "9999-12-31T23:59:59Z"; -} - -quick_error! { - /// Error parsing datetime (timestamp) - #[derive(Debug, PartialEq, Clone, Copy)] - pub enum Error { - /// Numeric component is out of range - OutOfRange { - display("numeric component is out of range") - } - /// Bad character where digit is expected - InvalidDigit { - display("bad character where digit is expected") - } - /// Other formatting errors - InvalidFormat { - display("timestamp format is invalid") - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -enum Precision { - Smart, - Seconds, - Millis, - Micros, - Nanos, -} - -/// A wrapper type that allows you to Display a SystemTime -#[derive(Debug, Clone)] -pub struct Rfc3339Timestamp(SystemTime, Precision); - -#[inline] -fn two_digits(b1: u8, b2: u8) -> Result { - if b1 < b'0' || b2 < b'0' || b1 > b'9' || b2 > b'9' { - return Err(Error::InvalidDigit); - } - Ok(((b1 - b'0')*10 + (b2 - b'0')) as u64) -} - -/// Parse RFC3339 timestamp `2018-02-14T00:28:07Z` -/// -/// Supported feature: any precision of fractional -/// digits `2018-02-14T00:28:07.133Z`. -/// -/// Unsupported feature: localized timestamps. Only UTC is supported. -pub fn parse_rfc3339(s: &str) -> Result { - if s.len() < "2018-02-14T00:28:07Z".len() { - return Err(Error::InvalidFormat); - } - let b = s.as_bytes(); - if b[10] != b'T' || b[b.len()-1] != b'Z' { - return Err(Error::InvalidFormat); - } - return parse_rfc3339_weak(s); -} - -/// Parse RFC3339-like timestamp `2018-02-14 00:28:07` -/// -/// Supported features: -/// -/// 1. Any precision of fractional digits `2018-02-14 00:28:07.133`. -/// 2. Supports timestamp with or without either of `T` or `Z` -/// 3. Anything valid for `parse_3339` is valid for this function -/// -/// Unsupported feature: localized timestamps. Only UTC is supported, even if -/// `Z` is not specified. -/// -/// This function is intended to use for parsing human input. Whereas -/// `parse_rfc3339` is for strings generated programmatically. -pub fn parse_rfc3339_weak(s: &str) -> Result { - if s.len() < "2018-02-14T00:28:07".len() { - return Err(Error::InvalidFormat); - } - let b = s.as_bytes(); // for careless slicing - if b[4] != b'-' || b[7] != b'-' || (b[10] != b'T' && b[10] != b' ') || - b[13] != b':' || b[16] != b':' - { - return Err(Error::InvalidFormat); - } - let year = two_digits(b[0], b[1])? * 100 + two_digits(b[2], b[3])?; - let month = two_digits(b[5], b[6])?; - let day = two_digits(b[8], b[9])?; - let hour = two_digits(b[11], b[12])?; - let minute = two_digits(b[14], b[15])?; - let mut second = two_digits(b[17], b[18])?; - - if year < 1970 || hour > 23 || minute > 59 || second > 60 { - return Err(Error::OutOfRange); - } - // TODO(tailhook) should we check that leaps second is only on midnight ? - if second == 60 { - second = 59 - }; - let leap_years = ((year - 1) - 1968) / 4 - ((year - 1) - 1900) / 100 + - ((year - 1) - 1600) / 400; - let leap = is_leap_year(year); - let (mut ydays, mdays) = match month { - 1 => (0, 31), - 2 if leap => (31, 29), - 2 => (31, 28), - 3 => (59, 31), - 4 => (90, 30), - 5 => (120, 31), - 6 => (151, 30), - 7 => (181, 31), - 8 => (212, 31), - 9 => (243, 30), - 10 => (273, 31), - 11 => (304, 30), - 12 => (334, 31), - _ => return Err(Error::OutOfRange), - }; - if day > mdays || day == 0 { - return Err(Error::OutOfRange); - } - ydays += day - 1; - if leap && month > 2 { - ydays += 1; - } - let days = (year - 1970) * 365 + leap_years + ydays; - - let time = second + minute * 60 + hour * 3600; - - let mut nanos = 0; - let mut mult = 100_000_000; - if b.get(19) == Some(&b'.') { - for idx in 20..b.len() { - if b[idx] == b'Z' { - if idx == b.len()-1 { - break; - } else { - return Err(Error::InvalidDigit); - } - } - if b[idx] < b'0' || b[idx] > b'9' { - return Err(Error::InvalidDigit); - } - nanos += mult * (b[idx] - b'0') as u32; - mult /= 10; - } - } else { - if b.len() != 19 && (b.len() > 20 || b[19] != b'Z') { - return Err(Error::InvalidFormat); - } - } - - let total_seconds = time + days * 86400; - if total_seconds > max::SECONDS { - return Err(Error::OutOfRange); - } - - return Ok(UNIX_EPOCH + Duration::new(total_seconds, nanos)); -} - -fn is_leap_year(y: u64) -> bool { - y % 4 == 0 && (!(y % 100 == 0) || y % 400 == 0) -} - -/// Format an RFC3339 timestamp `2018-02-14T00:28:07Z` -/// -/// This function formats timestamp with smart precision: i.e. if it has no -/// fractional seconds, they aren't written at all. And up to nine digits if -/// they are. -/// -/// The value is always UTC and ignores system timezone. -pub fn format_rfc3339(system_time: SystemTime) -> Rfc3339Timestamp { - return Rfc3339Timestamp(system_time, Precision::Smart); -} - -/// Format an RFC3339 timestamp `2018-02-14T00:28:07Z` -/// -/// This format always shows timestamp without fractional seconds. -/// -/// The value is always UTC and ignores system timezone. -pub fn format_rfc3339_seconds(system_time: SystemTime) -> Rfc3339Timestamp { - return Rfc3339Timestamp(system_time, Precision::Seconds); -} - -/// Format an RFC3339 timestamp `2018-02-14T00:28:07.000Z` -/// -/// This format always shows milliseconds even if millisecond value is zero. -/// -/// The value is always UTC and ignores system timezone. -pub fn format_rfc3339_millis(system_time: SystemTime) -> Rfc3339Timestamp { - return Rfc3339Timestamp(system_time, Precision::Millis); -} - -/// Format an RFC3339 timestamp `2018-02-14T00:28:07.000000Z` -/// -/// This format always shows microseconds even if microsecond value is zero. -/// -/// The value is always UTC and ignores system timezone. -pub fn format_rfc3339_micros(system_time: SystemTime) -> Rfc3339Timestamp { - return Rfc3339Timestamp(system_time, Precision::Micros); -} - -/// Format an RFC3339 timestamp `2018-02-14T00:28:07.000000000Z` -/// -/// This format always shows nanoseconds even if nanosecond value is zero. -/// -/// The value is always UTC and ignores system timezone. -pub fn format_rfc3339_nanos(system_time: SystemTime) -> Rfc3339Timestamp { - return Rfc3339Timestamp(system_time, Precision::Nanos); -} - -impl fmt::Display for Rfc3339Timestamp { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::Precision::*; - - let dur = self.0.duration_since(UNIX_EPOCH) - .expect("all times should be after the epoch"); - let secs_since_epoch = dur.as_secs(); - let nanos = dur.subsec_nanos(); - - if secs_since_epoch >= 253402300800 { // year 9999 - return Err(fmt::Error); - } - - /* 2000-03-01 (mod 400 year, immediately after feb29 */ - const LEAPOCH: i64 = 11017; - const DAYS_PER_400Y: i64 = 365*400 + 97; - const DAYS_PER_100Y: i64 = 365*100 + 24; - const DAYS_PER_4Y: i64 = 365*4 + 1; - - let days = (secs_since_epoch / 86400) as i64 - LEAPOCH; - let secs_of_day = secs_since_epoch % 86400; - - let mut qc_cycles = days / DAYS_PER_400Y; - let mut remdays = days % DAYS_PER_400Y; - - if remdays < 0 { - remdays += DAYS_PER_400Y; - qc_cycles -= 1; - } - - let mut c_cycles = remdays / DAYS_PER_100Y; - if c_cycles == 4 { c_cycles -= 1; } - remdays -= c_cycles * DAYS_PER_100Y; - - let mut q_cycles = remdays / DAYS_PER_4Y; - if q_cycles == 25 { q_cycles -= 1; } - remdays -= q_cycles * DAYS_PER_4Y; - - let mut remyears = remdays / 365; - if remyears == 4 { remyears -= 1; } - remdays -= remyears * 365; - - let mut year = 2000 + - remyears + 4*q_cycles + 100*c_cycles + 400*qc_cycles; - - let months = [31,30,31,30,31,31,30,31,30,31,31,29]; - let mut mon = 0; - for mon_len in months.iter() { - mon += 1; - if remdays < *mon_len { - break; - } - remdays -= *mon_len; - } - let mday = remdays+1; - let mon = if mon + 2 > 12 { - year += 1; - mon - 10 - } else { - mon + 2 - }; - - let mut buf: [u8; 30] = [ - // Too long to write as: b"0000-00-00T00:00:00.000000000Z" - b'0', b'0', b'0', b'0', b'-', b'0', b'0', b'-', b'0', b'0', b'T', - b'0', b'0', b':', b'0', b'0', b':', b'0', b'0', - b'.', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'Z', - ]; - buf[0] = b'0' + (year / 1000) as u8; - buf[1] = b'0' + (year / 100 % 10) as u8; - buf[2] = b'0' + (year / 10 % 10) as u8; - buf[3] = b'0' + (year % 10) as u8; - buf[5] = b'0' + (mon / 10) as u8; - buf[6] = b'0' + (mon % 10) as u8; - buf[8] = b'0' + (mday / 10) as u8; - buf[9] = b'0' + (mday % 10) as u8; - buf[11] = b'0' + (secs_of_day / 3600 / 10) as u8; - buf[12] = b'0' + (secs_of_day / 3600 % 10) as u8; - buf[14] = b'0' + (secs_of_day / 60 / 10 % 6) as u8; - buf[15] = b'0' + (secs_of_day / 60 % 10) as u8; - buf[17] = b'0' + (secs_of_day / 10 % 6) as u8; - buf[18] = b'0' + (secs_of_day % 10) as u8; - - let offset = if self.1 == Seconds || nanos == 0 && self.1 == Smart { - buf[19] = b'Z'; - 19 - } else if self.1 == Millis { - buf[20] = b'0' + (nanos / 100_000_000) as u8; - buf[21] = b'0' + (nanos / 10_000_000 % 10) as u8; - buf[22] = b'0' + (nanos / 1_000_000 % 10) as u8; - buf[23] = b'Z'; - 23 - } else if self.1 == Micros { - buf[20] = b'0' + (nanos / 100_000_000) as u8; - buf[21] = b'0' + (nanos / 10_000_000 % 10) as u8; - buf[22] = b'0' + (nanos / 1_000_000 % 10) as u8; - buf[23] = b'0' + (nanos / 100_000 % 10) as u8; - buf[24] = b'0' + (nanos / 10_000 % 10) as u8; - buf[25] = b'0' + (nanos / 1_000 % 10) as u8; - buf[26] = b'Z'; - 26 - } else { - buf[20] = b'0' + (nanos / 100_000_000) as u8; - buf[21] = b'0' + (nanos / 10_000_000 % 10) as u8; - buf[22] = b'0' + (nanos / 1_000_000 % 10) as u8; - buf[23] = b'0' + (nanos / 100_000 % 10) as u8; - buf[24] = b'0' + (nanos / 10_000 % 10) as u8; - buf[25] = b'0' + (nanos / 1_000 % 10) as u8; - buf[26] = b'0' + (nanos / 100 % 10) as u8; - buf[27] = b'0' + (nanos / 10 % 10) as u8; - buf[28] = b'0' + (nanos / 1 % 10) as u8; - // 29th is 'Z' - 29 - }; - - // we know our chars are all ascii - f.write_str(unsafe { str::from_utf8_unchecked(&buf[..offset+1]) }) - } -} - -#[cfg(test)] -mod test { - extern crate time; - extern crate rand; - - use std::str::from_utf8; - use self::rand::Rng; - use std::time::{UNIX_EPOCH, SystemTime, Duration}; - use super::{parse_rfc3339, parse_rfc3339_weak, format_rfc3339}; - use super::{format_rfc3339_millis, format_rfc3339_micros}; - use super::{format_rfc3339_nanos}; - use super::max; - - fn from_sec(sec: u64) -> (String, SystemTime) { - let s = time::at_utc(time::Timespec { sec: sec as i64, nsec: 0 }) - .rfc3339().to_string(); - let time = UNIX_EPOCH + Duration::new(sec, 0); - return (s, time) - } - - #[test] - #[cfg(all(target_pointer_width="32", target_os="linux"))] - fn year_after_2038_fails_gracefully() { - // next second - assert_eq!(parse_rfc3339("2038-01-19T03:14:08Z").unwrap_err(), - super::Error::OutOfRange); - assert_eq!(parse_rfc3339("9999-12-31T23:59:59Z").unwrap_err(), - super::Error::OutOfRange); - } - - #[test] - fn smoke_tests_parse() { - assert_eq!(parse_rfc3339("1970-01-01T00:00:00Z").unwrap(), - UNIX_EPOCH + Duration::new(0, 0)); - assert_eq!(parse_rfc3339("1970-01-01T00:00:01Z").unwrap(), - UNIX_EPOCH + Duration::new(1, 0)); - assert_eq!(parse_rfc3339("2018-02-13T23:08:32Z").unwrap(), - UNIX_EPOCH + Duration::new(1518563312, 0)); - assert_eq!(parse_rfc3339("2012-01-01T00:00:00Z").unwrap(), - UNIX_EPOCH + Duration::new(1325376000, 0)); - } - - #[test] - fn smoke_tests_format() { - assert_eq!( - format_rfc3339(UNIX_EPOCH + Duration::new(0, 0)).to_string(), - "1970-01-01T00:00:00Z"); - assert_eq!( - format_rfc3339(UNIX_EPOCH + Duration::new(1, 0)).to_string(), - "1970-01-01T00:00:01Z"); - assert_eq!( - format_rfc3339(UNIX_EPOCH + Duration::new(1518563312, 0)).to_string(), - "2018-02-13T23:08:32Z"); - assert_eq!( - format_rfc3339(UNIX_EPOCH + Duration::new(1325376000, 0)).to_string(), - "2012-01-01T00:00:00Z"); - } - - #[test] - fn smoke_tests_format_millis() { - assert_eq!( - format_rfc3339_millis(UNIX_EPOCH + - Duration::new(0, 0)).to_string(), - "1970-01-01T00:00:00.000Z"); - assert_eq!( - format_rfc3339_millis(UNIX_EPOCH + - Duration::new(1518563312, 123_000_000)).to_string(), - "2018-02-13T23:08:32.123Z"); - } - - #[test] - fn smoke_tests_format_micros() { - assert_eq!( - format_rfc3339_micros(UNIX_EPOCH + - Duration::new(0, 0)).to_string(), - "1970-01-01T00:00:00.000000Z"); - assert_eq!( - format_rfc3339_micros(UNIX_EPOCH + - Duration::new(1518563312, 123_000_000)).to_string(), - "2018-02-13T23:08:32.123000Z"); - assert_eq!( - format_rfc3339_micros(UNIX_EPOCH + - Duration::new(1518563312, 456_123_000)).to_string(), - "2018-02-13T23:08:32.456123Z"); - } - - #[test] - fn smoke_tests_format_nanos() { - assert_eq!( - format_rfc3339_nanos(UNIX_EPOCH + - Duration::new(0, 0)).to_string(), - "1970-01-01T00:00:00.000000000Z"); - assert_eq!( - format_rfc3339_nanos(UNIX_EPOCH + - Duration::new(1518563312, 123_000_000)).to_string(), - "2018-02-13T23:08:32.123000000Z"); - assert_eq!( - format_rfc3339_nanos(UNIX_EPOCH + - Duration::new(1518563312, 789_456_123)).to_string(), - "2018-02-13T23:08:32.789456123Z"); - } - - #[test] - fn upper_bound() { - let max = UNIX_EPOCH + Duration::new(max::SECONDS, 0); - assert_eq!(parse_rfc3339(&max::TIMESTAMP).unwrap(), max); - assert_eq!(format_rfc3339(max).to_string(), max::TIMESTAMP); - } - - #[test] - fn leap_second() { - assert_eq!(parse_rfc3339("2016-12-31T23:59:60Z").unwrap(), - UNIX_EPOCH + Duration::new(1483228799, 0)); - } - - #[test] - fn first_731_days() { - let year_start = 0; // 1970 - for day in 0.. (365 * 2 + 1) { // scan leap year and non-leap year - let (s, time) = from_sec(year_start + day * 86400); - assert_eq!(parse_rfc3339(&s).unwrap(), time); - assert_eq!(format_rfc3339(time).to_string(), s); - } - } - - #[test] - fn the_731_consecutive_days() { - let year_start = 1325376000; // 2012 - for day in 0.. (365 * 2 + 1) { // scan leap year and non-leap year - let (s, time) = from_sec(year_start + day * 86400); - assert_eq!(parse_rfc3339(&s).unwrap(), time); - assert_eq!(format_rfc3339(time).to_string(), s); - } - } - - #[test] - fn all_86400_seconds() { - let day_start = 1325376000; - for second in 0..86400 { // scan leap year and non-leap year - let (s, time) = from_sec(day_start + second); - assert_eq!(parse_rfc3339(&s).unwrap(), time); - assert_eq!(format_rfc3339(time).to_string(), s); - } - } - - #[test] - fn random_past() { - let upper = SystemTime::now().duration_since(UNIX_EPOCH).unwrap() - .as_secs(); - for _ in 0..10000 { - let sec = rand::thread_rng().gen_range(0, upper); - let (s, time) = from_sec(sec); - assert_eq!(parse_rfc3339(&s).unwrap(), time); - assert_eq!(format_rfc3339(time).to_string(), s); - } - } - - #[test] - fn random_wide_range() { - for _ in 0..100000 { - let sec = rand::thread_rng().gen_range(0, max::SECONDS); - let (s, time) = from_sec(sec); - assert_eq!(parse_rfc3339(&s).unwrap(), time); - assert_eq!(format_rfc3339(time).to_string(), s); - } - } - - #[test] - fn milliseconds() { - assert_eq!(parse_rfc3339("1970-01-01T00:00:00.123Z").unwrap(), - UNIX_EPOCH + Duration::new(0, 123000000)); - assert_eq!(format_rfc3339(UNIX_EPOCH + Duration::new(0, 123000000)) - .to_string(), "1970-01-01T00:00:00.123000000Z"); - } - - #[test] - #[should_panic(expected="OutOfRange")] - fn zero_month() { - parse_rfc3339("1970-00-01T00:00:00Z").unwrap(); - } - - #[test] - #[should_panic(expected="OutOfRange")] - fn big_month() { - parse_rfc3339("1970-32-01T00:00:00Z").unwrap(); - } - - #[test] - #[should_panic(expected="OutOfRange")] - fn zero_day() { - parse_rfc3339("1970-01-00T00:00:00Z").unwrap(); - } - - #[test] - #[should_panic(expected="OutOfRange")] - fn big_day() { - parse_rfc3339("1970-12-35T00:00:00Z").unwrap(); - } - - #[test] - #[should_panic(expected="OutOfRange")] - fn big_day2() { - parse_rfc3339("1970-02-30T00:00:00Z").unwrap(); - } - - #[test] - #[should_panic(expected="OutOfRange")] - fn big_second() { - parse_rfc3339("1970-12-30T00:00:78Z").unwrap(); - } - - #[test] - #[should_panic(expected="OutOfRange")] - fn big_minute() { - parse_rfc3339("1970-12-30T00:78:00Z").unwrap(); - } - - #[test] - #[should_panic(expected="OutOfRange")] - fn big_hour() { - parse_rfc3339("1970-12-30T24:00:00Z").unwrap(); - } - - #[test] - fn break_data() { - for pos in 0.."2016-12-31T23:59:60Z".len() { - let mut s = b"2016-12-31T23:59:60Z".to_vec(); - s[pos] = b'x'; - parse_rfc3339(from_utf8(&s).unwrap()).unwrap_err(); - } - } - - #[test] - fn weak_smoke_tests() { - assert_eq!(parse_rfc3339_weak("1970-01-01 00:00:00").unwrap(), - UNIX_EPOCH + Duration::new(0, 0)); - parse_rfc3339("1970-01-01 00:00:00").unwrap_err(); - - assert_eq!(parse_rfc3339_weak("1970-01-01 00:00:00.000123").unwrap(), - UNIX_EPOCH + Duration::new(0, 123000)); - parse_rfc3339("1970-01-01 00:00:00.000123").unwrap_err(); - - assert_eq!(parse_rfc3339_weak("1970-01-01T00:00:00.000123").unwrap(), - UNIX_EPOCH + Duration::new(0, 123000)); - parse_rfc3339("1970-01-01T00:00:00.000123").unwrap_err(); - - assert_eq!(parse_rfc3339_weak("1970-01-01 00:00:00.000123Z").unwrap(), - UNIX_EPOCH + Duration::new(0, 123000)); - parse_rfc3339("1970-01-01 00:00:00.000123Z").unwrap_err(); - - assert_eq!(parse_rfc3339_weak("1970-01-01 00:00:00Z").unwrap(), - UNIX_EPOCH + Duration::new(0, 0)); - parse_rfc3339("1970-01-01 00:00:00Z").unwrap_err(); - } -} diff --git a/third_party/rust/humantime-1.3.0/src/duration.rs b/third_party/rust/humantime-1.3.0/src/duration.rs deleted file mode 100644 index 9fafa84bdca8..000000000000 --- a/third_party/rust/humantime-1.3.0/src/duration.rs +++ /dev/null @@ -1,411 +0,0 @@ -use std::fmt; -use std::str::Chars; -use std::time::Duration; -use std::error::Error as StdError; - -quick_error! { - /// Error parsing human-friendly duration - #[derive(Debug, PartialEq, Clone, Copy)] - pub enum Error { - /// Invalid character during parsing - /// - /// More specifically anything that is not alphanumeric is prohibited - /// - /// The field is an byte offset of the character in the string. - InvalidCharacter(offset: usize) { - display("invalid character at {}", offset) - description("invalid character") - } - /// Non-numeric value where number is expected - /// - /// This usually means that either time unit is broken into words, - /// e.g. `m sec` instead of `msec`, or just number is omitted, - /// for example `2 hours min` instead of `2 hours 1 min` - /// - /// The field is an byte offset of the errorneous character - /// in the string. - NumberExpected(offset: usize) { - display("expected number at {}", offset) - description("expected number") - } - /// Unit in the number is not one of allowed units - /// - /// See documentation of `parse_duration` for the list of supported - /// time units. - /// - /// The two fields are start and end (exclusive) of the slice from - /// the original string, containing errorneous value - UnknownUnit(start: usize, end: usize) { - display("unknown unit at {}-{}", start, end) - description("unknown unit") - } - /// The numeric value is too large - /// - /// Usually this means value is too large to be useful. If user writes - /// data in subsecond units, then the maximum is about 3k years. When - /// using seconds, or larger units, the limit is even larger. - NumberOverflow { - display(self_) -> ("{}", self_.description()) - description("number is too large") - } - /// The value was an empty string (or consists only whitespace) - Empty { - display(self_) -> ("{}", self_.description()) - description("value was empty") - } - } - -} - -/// A wrapper type that allows you to Display a Duration -#[derive(Debug, Clone)] -pub struct FormattedDuration(Duration); - -trait OverflowOp: Sized { - fn mul(self, other: Self) -> Result; - fn add(self, other: Self) -> Result; -} - -impl OverflowOp for u64 { - fn mul(self, other: Self) -> Result { - self.checked_mul(other).ok_or(Error::NumberOverflow) - } - fn add(self, other: Self) -> Result { - self.checked_add(other).ok_or(Error::NumberOverflow) - } -} - -struct Parser<'a> { - iter: Chars<'a>, - src: &'a str, - current: (u64, u64), -} - -impl<'a> Parser<'a> { - fn off(&self) -> usize { - self.src.len() - self.iter.as_str().len() - } - - fn parse_first_char(&mut self) -> Result, Error> { - let off = self.off(); - for c in self.iter.by_ref() { - match c { - '0'...'9' => { - return Ok(Some(c as u64 - '0' as u64)); - } - c if c.is_whitespace() => continue, - _ => { - return Err(Error::NumberExpected(off)); - } - } - } - return Ok(None); - } - fn parse_unit(&mut self, n: u64, start: usize, end: usize) - -> Result<(), Error> - { - let (mut sec, nsec) = match &self.src[start..end] { - "nanos" | "nsec" | "ns" => (0u64, n), - "usec" | "us" => (0u64, try!(n.mul(1000))), - "millis" | "msec" | "ms" => (0u64, try!(n.mul(1000_000))), - "seconds" | "second" | "secs" | "sec" | "s" => (n, 0), - "minutes" | "minute" | "min" | "mins" | "m" - => (try!(n.mul(60)), 0), - "hours" | "hour" | "hr" | "hrs" | "h" => (try!(n.mul(3600)), 0), - "days" | "day" | "d" => (try!(n.mul(86400)), 0), - "weeks" | "week" | "w" => (try!(n.mul(86400*7)), 0), - "months" | "month" | "M" => (try!(n.mul(2630016)), 0), // 30.44d - "years" | "year" | "y" => (try!(n.mul(31557600)), 0), // 365.25d - _ => return Err(Error::UnknownUnit(start, end)), - }; - let mut nsec = try!(self.current.1.add(nsec)); - if nsec > 1000_000_000 { - sec = try!(sec.add(nsec / 1000_000_000)); - nsec %= 1000_000_000; - } - sec = try!(self.current.0.add(sec)); - self.current = (sec, nsec); - Ok(()) - } - - fn parse(mut self) -> Result { - let mut n = try!(try!(self.parse_first_char()).ok_or(Error::Empty)); - 'outer: loop { - let mut off = self.off(); - while let Some(c) = self.iter.next() { - match c { - '0'...'9' => { - n = try!(n.checked_mul(10) - .and_then(|x| x.checked_add(c as u64 - '0' as u64)) - .ok_or(Error::NumberOverflow)); - } - c if c.is_whitespace() => {} - 'a'...'z' | 'A'...'Z' => { - break; - } - _ => { - return Err(Error::InvalidCharacter(off)); - } - } - off = self.off(); - } - let start = off; - let mut off = self.off(); - while let Some(c) = self.iter.next() { - match c { - '0'...'9' => { - try!(self.parse_unit(n, start, off)); - n = c as u64 - '0' as u64; - continue 'outer; - } - c if c.is_whitespace() => break, - 'a'...'z' | 'A'...'Z' => {} - _ => { - return Err(Error::InvalidCharacter(off)); - } - } - off = self.off(); - } - try!(self.parse_unit(n, start, off)); - n = match try!(self.parse_first_char()) { - Some(n) => n, - None => return Ok( - Duration::new(self.current.0, self.current.1 as u32)), - }; - } - } - -} - -/// Parse duration object `1hour 12min 5s` -/// -/// The duration object is a concatenation of time spans. Where each time -/// span is an integer number and a suffix. Supported suffixes: -/// -/// * `nsec`, `ns` -- microseconds -/// * `usec`, `us` -- microseconds -/// * `msec`, `ms` -- milliseconds -/// * `seconds`, `second`, `sec`, `s` -/// * `minutes`, `minute`, `min`, `m` -/// * `hours`, `hour`, `hr`, `h` -/// * `days`, `day`, `d` -/// * `weeks`, `week`, `w` -/// * `months`, `month`, `M` -- defined as 30.44 days -/// * `years`, `year`, `y` -- defined as 365.25 days -/// -/// # Examples -/// -/// ``` -/// use std::time::Duration; -/// use humantime::parse_duration; -/// -/// assert_eq!(parse_duration("2h 37min"), Ok(Duration::new(9420, 0))); -/// assert_eq!(parse_duration("32ms"), Ok(Duration::new(0, 32_000_000))); -/// ``` -pub fn parse_duration(s: &str) -> Result { - Parser { - iter: s.chars(), - src: s, - current: (0, 0), - }.parse() -} - -/// Formats duration into a human-readable string -/// -/// Note: this format is guaranteed to have same value when using -/// parse_duration, but we can change some details of the exact composition -/// of the value. -/// -/// # Examples -/// -/// ``` -/// use std::time::Duration; -/// use humantime::format_duration; -/// -/// let val1 = Duration::new(9420, 0); -/// assert_eq!(format_duration(val1).to_string(), "2h 37m"); -/// let val2 = Duration::new(0, 32_000_000); -/// assert_eq!(format_duration(val2).to_string(), "32ms"); -/// ``` -pub fn format_duration(val: Duration) -> FormattedDuration { - FormattedDuration(val) -} - -fn item_plural(f: &mut fmt::Formatter, started: &mut bool, - name: &str, value: u64) - -> fmt::Result -{ - if value > 0 { - if *started { - f.write_str(" ")?; - } - write!(f, "{}{}", value, name)?; - if value > 1 { - f.write_str("s")?; - } - *started = true; - } - Ok(()) -} -fn item(f: &mut fmt::Formatter, started: &mut bool, name: &str, value: u32) - -> fmt::Result -{ - if value > 0 { - if *started { - f.write_str(" ")?; - } - write!(f, "{}{}", value, name)?; - *started = true; - } - Ok(()) -} - -impl fmt::Display for FormattedDuration { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let secs = self.0.as_secs(); - let nanos = self.0.subsec_nanos(); - - if secs == 0 && nanos == 0 { - f.write_str("0s")?; - return Ok(()); - } - - let years = secs / 31557600; // 365.25d - let ydays = secs % 31557600; - let months = ydays / 2630016; // 30.44d - let mdays = ydays % 2630016; - let days = mdays / 86400; - let day_secs = mdays % 86400; - let hours = day_secs / 3600; - let minutes = day_secs % 3600 / 60; - let seconds = day_secs % 60; - - let millis = nanos / 1_000_000; - let micros = nanos / 1000 % 1000; - let nanosec = nanos % 1000; - - let ref mut started = false; - item_plural(f, started, "year", years)?; - item_plural(f, started, "month", months)?; - item_plural(f, started, "day", days)?; - item(f, started, "h", hours as u32)?; - item(f, started, "m", minutes as u32)?; - item(f, started, "s", seconds as u32)?; - item(f, started, "ms", millis)?; - item(f, started, "us", micros)?; - item(f, started, "ns", nanosec)?; - Ok(()) - } -} - -#[cfg(test)] -mod test { - extern crate rand; - - use std::time::Duration; - use self::rand::Rng; - use super::{parse_duration, format_duration}; - use super::Error; - - #[test] - fn test_units() { - assert_eq!(parse_duration("17nsec"), Ok(Duration::new(0, 17))); - assert_eq!(parse_duration("17nanos"), Ok(Duration::new(0, 17))); - assert_eq!(parse_duration("33ns"), Ok(Duration::new(0, 33))); - assert_eq!(parse_duration("3usec"), Ok(Duration::new(0, 3000))); - assert_eq!(parse_duration("78us"), Ok(Duration::new(0, 78000))); - assert_eq!(parse_duration("31msec"), Ok(Duration::new(0, 31000000))); - assert_eq!(parse_duration("31millis"), Ok(Duration::new(0, 31000000))); - assert_eq!(parse_duration("6ms"), Ok(Duration::new(0, 6000000))); - assert_eq!(parse_duration("3000s"), Ok(Duration::new(3000, 0))); - assert_eq!(parse_duration("300sec"), Ok(Duration::new(300, 0))); - assert_eq!(parse_duration("300secs"), Ok(Duration::new(300, 0))); - assert_eq!(parse_duration("50seconds"), Ok(Duration::new(50, 0))); - assert_eq!(parse_duration("1second"), Ok(Duration::new(1, 0))); - assert_eq!(parse_duration("100m"), Ok(Duration::new(6000, 0))); - assert_eq!(parse_duration("12min"), Ok(Duration::new(720, 0))); - assert_eq!(parse_duration("12mins"), Ok(Duration::new(720, 0))); - assert_eq!(parse_duration("1minute"), Ok(Duration::new(60, 0))); - assert_eq!(parse_duration("7minutes"), Ok(Duration::new(420, 0))); - assert_eq!(parse_duration("2h"), Ok(Duration::new(7200, 0))); - assert_eq!(parse_duration("7hr"), Ok(Duration::new(25200, 0))); - assert_eq!(parse_duration("7hrs"), Ok(Duration::new(25200, 0))); - assert_eq!(parse_duration("1hour"), Ok(Duration::new(3600, 0))); - assert_eq!(parse_duration("24hours"), Ok(Duration::new(86400, 0))); - assert_eq!(parse_duration("1day"), Ok(Duration::new(86400, 0))); - assert_eq!(parse_duration("2days"), Ok(Duration::new(172800, 0))); - assert_eq!(parse_duration("365d"), Ok(Duration::new(31536000, 0))); - assert_eq!(parse_duration("1week"), Ok(Duration::new(604800, 0))); - assert_eq!(parse_duration("7weeks"), Ok(Duration::new(4233600, 0))); - assert_eq!(parse_duration("52w"), Ok(Duration::new(31449600, 0))); - assert_eq!(parse_duration("1month"), Ok(Duration::new(2630016, 0))); - assert_eq!(parse_duration("3months"), Ok(Duration::new(3*2630016, 0))); - assert_eq!(parse_duration("12M"), Ok(Duration::new(31560192, 0))); - assert_eq!(parse_duration("1year"), Ok(Duration::new(31557600, 0))); - assert_eq!(parse_duration("7years"), Ok(Duration::new(7*31557600, 0))); - assert_eq!(parse_duration("17y"), Ok(Duration::new(536479200, 0))); - } - - #[test] - fn test_combo() { - assert_eq!(parse_duration("20 min 17 nsec "), Ok(Duration::new(1200, 17))); - assert_eq!(parse_duration("2h 15m"), Ok(Duration::new(8100, 0))); - } - - #[test] - fn all_86400_seconds() { - for second in 0..86400 { // scan leap year and non-leap year - let d = Duration::new(second, 0); - assert_eq!(d, - parse_duration(&format_duration(d).to_string()).unwrap()); - } - } - - #[test] - fn random_second() { - for _ in 0..10000 { - let sec = rand::thread_rng().gen_range(0, 253370764800); - let d = Duration::new(sec, 0); - assert_eq!(d, - parse_duration(&format_duration(d).to_string()).unwrap()); - } - } - - #[test] - fn random_any() { - for _ in 0..10000 { - let sec = rand::thread_rng().gen_range(0, 253370764800); - let nanos = rand::thread_rng().gen_range(0, 1_000_000_000); - let d = Duration::new(sec, nanos); - assert_eq!(d, - parse_duration(&format_duration(d).to_string()).unwrap()); - } - } - - #[test] - fn test_overlow() { - // Overflow on subseconds is earlier because of how we do conversion - // we could fix it, but I don't see any good reason for this - assert_eq!(parse_duration("100000000000000000000ns"), - Err(Error::NumberOverflow)); - assert_eq!(parse_duration("100000000000000000us"), - Err(Error::NumberOverflow)); - assert_eq!(parse_duration("100000000000000ms"), - Err(Error::NumberOverflow)); - - assert_eq!(parse_duration("100000000000000000000s"), - Err(Error::NumberOverflow)); - assert_eq!(parse_duration("10000000000000000000m"), - Err(Error::NumberOverflow)); - assert_eq!(parse_duration("1000000000000000000h"), - Err(Error::NumberOverflow)); - assert_eq!(parse_duration("100000000000000000d"), - Err(Error::NumberOverflow)); - assert_eq!(parse_duration("10000000000000000w"), - Err(Error::NumberOverflow)); - assert_eq!(parse_duration("1000000000000000M"), - Err(Error::NumberOverflow)); - assert_eq!(parse_duration("10000000000000y"), - Err(Error::NumberOverflow)); - } -} diff --git a/third_party/rust/humantime-1.3.0/src/lib.rs b/third_party/rust/humantime-1.3.0/src/lib.rs deleted file mode 100644 index 6d6c707e1d5d..000000000000 --- a/third_party/rust/humantime-1.3.0/src/lib.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! Human-friendly time parser and formatter -//! -//! Features: -//! -//! * Parses durations in free form like `15days 2min 2s` -//! * Formats durations in similar form `2years 2min 12us` -//! * Parses and formats timestamp in `rfc3339` format: `2018-01-01T12:53:00Z` -//! * Parses timestamps in a weaker format: `2018-01-01 12:53:00` -//! -//! Timestamp parsing/formatting is super-fast because format is basically -//! fixed. -//! -//! See [serde-humantime] for serde integration. -//! -//! [serde-humantime]: https://docs.rs/serde-humantime/0.1.1/serde_humantime/ -#![warn(missing_debug_implementations)] -#![warn(missing_docs)] - -#[macro_use] extern crate quick_error; - -mod duration; -mod wrapper; -mod date; - -pub use duration::{parse_duration, Error as DurationError}; -pub use duration::{format_duration, FormattedDuration}; -pub use wrapper::{Duration, Timestamp}; -pub use date::{parse_rfc3339, parse_rfc3339_weak, Error as TimestampError}; -pub use date::{ - format_rfc3339, format_rfc3339_micros, format_rfc3339_millis, format_rfc3339_nanos, - format_rfc3339_seconds, -}; -pub use date::{Rfc3339Timestamp}; diff --git a/third_party/rust/humantime-1.3.0/src/wrapper.rs b/third_party/rust/humantime-1.3.0/src/wrapper.rs deleted file mode 100644 index df01d791a819..000000000000 --- a/third_party/rust/humantime-1.3.0/src/wrapper.rs +++ /dev/null @@ -1,107 +0,0 @@ -use std::str::FromStr; -use std::ops::Deref; -use std::fmt; -use std::time::{Duration as StdDuration, SystemTime}; - -use duration::{self, parse_duration, format_duration}; -use date::{self, parse_rfc3339_weak, format_rfc3339}; - -/// A wrapper for duration that has `FromStr` implementation -/// -/// This is useful if you want to use it somewhere where `FromStr` is -/// expected. -/// -/// See `parse_duration` for the description of the format. -/// -/// # Example -/// -/// ``` -/// use std::time::Duration; -/// let x: Duration; -/// x = "12h 5min 2ns".parse::().unwrap().into(); -/// assert_eq!(x, Duration::new(12*3600 + 5*60, 2)) -/// ``` -/// -#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] -pub struct Duration(StdDuration); - -/// A wrapper for SystemTime that has `FromStr` implementation -/// -/// This is useful if you want to use it somewhere where `FromStr` is -/// expected. -/// -/// See `parse_rfc3339_weak` for the description of the format. The "weak" -/// format is used as it's more pemissive for human input as this is the -/// expected use of the type (e.g. command-line parsing). -/// -/// # Example -/// -/// ``` -/// use std::time::SystemTime; -/// let x: SystemTime; -/// x = "2018-02-16T00:31:37Z".parse::().unwrap().into(); -/// assert_eq!(humantime::format_rfc3339(x).to_string(), "2018-02-16T00:31:37Z"); -/// ``` -/// -#[derive(Debug, PartialEq, Eq, Clone)] -pub struct Timestamp(SystemTime); - -impl AsRef for Duration { - fn as_ref(&self) -> &StdDuration { &self.0 } -} - -impl Deref for Duration { - type Target = StdDuration; - fn deref(&self) -> &StdDuration { &self.0 } -} - -impl Into for Duration { - fn into(self) -> StdDuration { self.0 } -} - -impl From for Duration { - fn from(dur: StdDuration) -> Duration { Duration(dur) } -} - -impl FromStr for Duration { - type Err = duration::Error; - fn from_str(s: &str) -> Result { - parse_duration(s).map(Duration) - } -} - -impl fmt::Display for Duration { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - format_duration(self.0).fmt(f) - } -} - -impl AsRef for Timestamp { - fn as_ref(&self) -> &SystemTime { &self.0 } -} - -impl Deref for Timestamp { - type Target = SystemTime; - fn deref(&self) -> &SystemTime { &self.0 } -} - -impl Into for Timestamp { - fn into(self) -> SystemTime { self.0 } -} - -impl From for Timestamp { - fn from(dur: SystemTime) -> Timestamp { Timestamp(dur) } -} - -impl FromStr for Timestamp { - type Err = date::Error; - fn from_str(s: &str) -> Result { - parse_rfc3339_weak(s).map(Timestamp) - } -} - -impl fmt::Display for Timestamp { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - format_rfc3339(self.0).fmt(f) - } -} diff --git a/third_party/rust/humantime-1.3.0/vagga.yaml b/third_party/rust/humantime-1.3.0/vagga.yaml deleted file mode 100644 index b5d6b8b7c005..000000000000 --- a/third_party/rust/humantime-1.3.0/vagga.yaml +++ /dev/null @@ -1,92 +0,0 @@ -commands: - - cargo: !Command - description: Run any cargo command - container: ubuntu - run: [cargo] - - make: !Command - description: Build the library - container: ubuntu - run: [cargo, build] - - test64: !Command - description: Test the 64bit library - container: ubuntu - environ: { RUST_BACKTRACE: 1 } - run: [cargo, test] - - test32: !Command - description: Test the 32bit library - container: ubuntu32 - environ: { RUST_BACKTRACE: 1 } - run: [cargo, test] - - test: !Command - description: Test the 64bit library - container: ubuntu - environ: { RUST_BACKTRACE: 1 } - prerequisites: [test64, test32] - run: [echo, okay] - - bench: !Command - description: Run benchmarks - container: bench - environ: { RUST_BACKTRACE: 1 } - run: [cargo, bench] - - _bulk: !Command - description: Run `bulk` command (for version bookkeeping) - container: ubuntu - run: [bulk] - -containers: - - ubuntu: - setup: - - !Ubuntu xenial - - !UbuntuUniverse - - !Install [ca-certificates, build-essential, vim] - - - !TarInstall - url: "https://static.rust-lang.org/dist/rust-1.24.0-x86_64-unknown-linux-gnu.tar.gz" - script: "./install.sh --prefix=/usr \ - --components=rustc,rust-std-x86_64-unknown-linux-gnu,cargo" - - &bulk !Tar - url: "https://github.com/tailhook/bulk/releases/download/v0.4.10/bulk-v0.4.10.tar.gz" - sha256: 481513f8a0306a9857d045497fb5b50b50a51e9ff748909ecf7d2bda1de275ab - path: / - - environ: - HOME: /work/target - USER: pc - - ubuntu32: - setup: - - !UbuntuRelease - codename: xenial - arch: i386 - - !UbuntuUniverse - - !Install [ca-certificates, build-essential, vim] - - - !TarInstall - url: "https://static.rust-lang.org/dist/rust-1.24.0-i686-unknown-linux-gnu.tar.gz" - script: "./install.sh --prefix=/usr \ - --components=rustc,rust-std-i686-unknown-linux-gnu,cargo" - - environ: - HOME: /work/target - USER: pc - - bench: - setup: - - !Ubuntu xenial - - !Install [ca-certificates, wget, build-essential] - - !TarInstall - url: https://static.rust-lang.org/dist/rust-nightly-x86_64-unknown-linux-gnu.tar.gz - script: | - ./install.sh --prefix=/usr \ - --components=rustc,rust-std-x86_64-unknown-linux-gnu,cargo - environ: - HOME: /work/target - USER: pc diff --git a/third_party/rust/mp4parse/.cargo-checksum.json b/third_party/rust/mp4parse/.cargo-checksum.json index 32354e0c42ae..44f652a2920c 100644 --- a/third_party/rust/mp4parse/.cargo-checksum.json +++ b/third_party/rust/mp4parse/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"105033ac7475000fc0d13cb51973a6fe439a167d05ef79d7db1aa0f82618dedd","benches/avif_benchmark.rs":"e4bdd69c7b434448ef7080bbf488b2f64c2c88121fe1c1f7e9d9c8def3d648ae","src/boxes.rs":"756a3d3638d91fc8e2e58a3e41e663b46d6381539ec12b2e7b6980b205ef4ed2","src/lib.rs":"d5d884e46f7f70301efda1388e6b0c9b0ff7bd0de3eccc0276c45ea9c0c1c055","src/macros.rs":"76c840f9299797527fe71aa5b378ffb01312767372b45cc62deddb19775400ae","src/tests.rs":"20b47bac38d76f0c408485cd980c4bd16cf3f0d3254fff273a16f20c54362ceb","tests/bug-1661347.avif":"a4741189d897401c746492d780bccf4c42dddde8f46d01a791f9656aac2ab164","tests/corrupt/bad-ipma-flags.avif":"ecde7997b97db1910b9dcc7ca8e3c8957da0e83681ea9008c66dc9f12b78ad19","tests/corrupt/bad-ipma-version.avif":"7f9a1a0b4ebbf8d800d22eaae5ff78970cc6b811317db6c1467c6883952b7c9b","tests/corrupt/bug-1655846.avif":"e0a5a06225800fadf05f5352503a4cec11af73eef705c43b4acab5f4a99dea50","tests/corrupt/bug-1661347.avif":"31c26561e1d9eafb60f7c5968b82a0859d203d73f17f26b29276256acee12966","tests/kodim-extents.avif":"e4de6d124535206c3daca797e64cccc6a5b439f93733af52a95b1e82d581a78b","tests/overflow.rs":"16b591d8def1a155b3b997622f6ea255536870d99c3d8f97c51755b77a50de3c","tests/public.rs":"e6365f9d992a318f7b308cd7ba9cd8b78df84b8893af4baf0c1edb5f39342ed9"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"5f772c84750dde85555ebe9e01e30266c515402b44ac2735f183a5b143c43196","src/boxes.rs":"7f989f8e91d173f323db22a8748ea911dd143c6304f66ccaf6ebc97d68ca5536","src/lib.rs":"4d4152c72ef49ced0a467879c51ff9e2430f704cd13a8eea4dc891b5f5843280","src/macros.rs":"76c840f9299797527fe71aa5b378ffb01312767372b45cc62deddb19775400ae","src/tests.rs":"6c1b8822410f5410d991f553925d3591f9c7ce41891191da8b3da62e783ebb02","tests/bug-1655846.avif":"e0a5a06225800fadf05f5352503a4cec11af73eef705c43b4acab5f4a99dea50","tests/bug-1661347.avif":"31c26561e1d9eafb60f7c5968b82a0859d203d73f17f26b29276256acee12966","tests/overflow.rs":"16b591d8def1a155b3b997622f6ea255536870d99c3d8f97c51755b77a50de3c","tests/public.rs":"5ff2282b0f84f55e25e18dcca9acc5bffde806d885c897354e5f65292f295557"},"package":null} \ No newline at end of file diff --git a/third_party/rust/mp4parse/Cargo.toml b/third_party/rust/mp4parse/Cargo.toml index 02754e6c8fe3..894d01fdf8f6 100644 --- a/third_party/rust/mp4parse/Cargo.toml +++ b/third_party/rust/mp4parse/Cargo.toml @@ -27,8 +27,7 @@ travis-ci = { repository = "https://github.com/mozilla/mp4parse-rust" } [dependencies] byteorder = "1.2.1" bitreader = { version = "0.3.2" } -env_logger = "0.7.1" -fallible_collections = { version = "0.3", features = ["std_io"] } +fallible_collections = { version = "0.2", features = ["std_io"] } hashbrown = "0.9" num-traits = "=0.2.10" log = "0.4" @@ -36,13 +35,5 @@ static_assertions = "1.1.0" [dev-dependencies] test-assembler = "0.1.2" +env_logger = "0.7.1" walkdir = "2.3.1" -criterion = "0.3" - -[[bench]] -name = "avif_benchmark" -harness = false - -# See https://bheisler.github.io/criterion.rs/book/faq.html#cargo-bench-gives-unrecognized-option-errors-for-valid-command-line-options -[lib] -bench = false diff --git a/third_party/rust/mp4parse/benches/avif_benchmark.rs b/third_party/rust/mp4parse/benches/avif_benchmark.rs deleted file mode 100644 index dabe1c90a6e6..000000000000 --- a/third_party/rust/mp4parse/benches/avif_benchmark.rs +++ /dev/null @@ -1,23 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. -extern crate criterion; -extern crate mp4parse as mp4; - -use criterion::{criterion_group, criterion_main, Criterion}; -use std::fs::File; - -fn criterion_benchmark(c: &mut Criterion) { - c.bench_function("avif_largest", |b| b.iter(|| avif_largest())); -} - -criterion_group!(benches, criterion_benchmark); -criterion_main!(benches); - -fn avif_largest() { - let input = &mut File::open( - "av1-avif/testFiles/Netflix/avif/cosmos_frame05000_yuv444_12bpc_bt2020_pq_qlossless.avif", - ) - .expect("Unknown file"); - assert!(mp4::read_avif(input).is_ok()); -} diff --git a/third_party/rust/mp4parse/src/boxes.rs b/third_party/rust/mp4parse/src/boxes.rs index 2960710892de..2338d1ca3cd6 100644 --- a/third_party/rust/mp4parse/src/boxes.rs +++ b/third_party/rust/mp4parse/src/boxes.rs @@ -97,7 +97,6 @@ impl PartialEq<&[u8; 4]> for FourCC { } } -#[deny(unreachable_patterns)] box_database!( FileTypeBox 0x6674_7970, // "ftyp" MediaDataBox 0x6d64_6174, // "mdat" @@ -115,13 +114,6 @@ box_database!( MediaHeaderBox 0x6d64_6864, // "mdhd" HandlerBox 0x6864_6c72, // "hdlr" MediaInformationBox 0x6d69_6e66, // "minf" - ImageReferenceBox 0x6972_6566, // "iref" - ImagePropertiesBox 0x6970_7270, // "iprp" - ItemPropertyContainerBox 0x6970_636f, // "ipco" - ItemPropertyAssociationBox 0x6970_6d61, // "ipma" - ColorInformationBox 0x636f_6c72, // "colr" - PixelInformationBox 0x7069_7869, // "pixi" - AuxiliaryTypeProperty 0x6175_7843, // "auxC" SampleTableBox 0x7374_626c, // "stbl" SampleDescriptionBox 0x7374_7364, // "stsd" TimeToSampleBox 0x7374_7473, // "stts" @@ -158,8 +150,8 @@ box_database!( SchemeTypeBox 0x7363_686d, // "schm" MP3AudioSampleEntry 0x2e6d_7033, // ".mp3" - from F4V. CompositionOffsetBox 0x6374_7473, // "ctts" - LPCMAudioSampleEntry 0x6c70_636d, // "lpcm" - quicktime atom - ALACSpecificBox 0x616c_6163, // "alac" - Also used by ALACSampleEntry + LPCMAudioSampleEntry 0x6C70_636D, // "lpcm" - quicktime atom + ALACSpecificBox 0x616C_6163, // "alac" - Also used by ALACSampleEntry UuidBox 0x7575_6964, // "uuid" MetadataBox 0x6d65_7461, // "meta" MetadataHeaderBox 0x6d68_6472, // "mhdr" diff --git a/third_party/rust/mp4parse/src/lib.rs b/third_party/rust/mp4parse/src/lib.rs index 802ec9843a77..e8f9916b3c42 100644 --- a/third_party/rust/mp4parse/src/lib.rs +++ b/third_party/rust/mp4parse/src/lib.rs @@ -13,13 +13,12 @@ extern crate fallible_collections; extern crate num_traits; use bitreader::{BitReader, ReadInto}; use byteorder::{ReadBytesExt, WriteBytesExt}; - use fallible_collections::TryRead; -use fallible_collections::TryReserveError; use num_traits::Num; use std::convert::{TryFrom, TryInto as _}; use std::io::Cursor; use std::io::{Read, Take}; +use std::ops::{Range, RangeFrom}; #[macro_use] mod macros; @@ -201,14 +200,14 @@ impl From for std::io::Error { } } -impl From for Error { - fn from(_: TryReserveError) -> Error { +impl From for Error { + fn from(_: fallible_collections::TryReserveError) -> Error { Error::OutOfMemory } } /// Result shorthand using our Error enum. -pub type Result = std::result::Result; +pub type Result = std::result::Result; /// Basic ISO box structure. /// @@ -217,7 +216,7 @@ pub type Result = std::result::Result; /// four-byte box type which identifies the type of the box. Together these /// are enough to interpret the contents of that section of the file. /// -/// See ISOBMFF (ISO 14496-12:2015) § 4.2 +/// See ISO 14496-12:2015 § 4.2 #[derive(Debug, Clone, Copy)] struct BoxHeader { /// Box type. @@ -377,7 +376,7 @@ pub enum SampleEntry { } /// An Elementary Stream Descriptor -/// See MPEG-4 Systems (ISO 14496-1:2010) § 7.2.6.5 +/// See ISO 14496-1:2010 § 7.2.6.5 #[allow(non_camel_case_types)] #[derive(Debug, Default)] pub struct ES_Descriptor { @@ -442,13 +441,13 @@ pub struct VPxConfigBox { /// An integer that specifies the bit depth of the luma and color components. Valid values /// are 8, 10, and 12. pub bit_depth: u8, - /// Really an enum defined by the "Colour primaries" section of ISO 23091-2:2019 § 8.1. + /// Really an enum defined by the "Colour primaries" section of ISO/IEC 23001-8:2016. pub colour_primaries: u8, /// Really an enum defined by "VP Codec ISO Media File Format Binding". pub chroma_subsampling: u8, - /// Really an enum defined by the "Transfer characteristics" section of ISO 23091-2:2019 § 8.2. + /// Really an enum defined by the "Transfer characteristics" section of ISO/IEC 23001-8:2016. transfer_characteristics: u8, - /// Really an enum defined by the "Matrix coefficients" section of ISO 23091-2:2019 § 8.3. + /// Really an enum defined by the "Matrix coefficients" section of ISO/IEC 23001-8:2016. /// Available in 'VP Codec ISO Media File Format' version 1 only. matrix_coefficients: Option, /// Indicates the black level and range of the luma and chroma signals. 0 = legal range @@ -744,249 +743,85 @@ impl MediaContext { } } -/// An ISOBMFF item as described by an iloc box. For the sake of avoiding copies, -/// this can either be represented by the `Location` variant, which indicates -/// where the data exists within a `MediaDataBox` stored separately, or the -/// `Data` variant which owns the data. Unfortunately, it's not simple to -/// represent this as a std::borrow::Cow, or other reference-based type, because -/// multiple instances may references different parts of the same `MediaDataBox` -/// and we want to avoid the copy that splitting the storage would entail. -#[derive(Debug)] -enum AvifItem { - Location(Extent), - Data(TryVec), -} - -#[derive(Debug)] +#[derive(Debug, Default)] pub struct AvifContext { - /// Referred to by the `Location` variants of the `AvifItem`s in this struct - item_storage: TryVec, - /// The item indicated by the `pitm` box, See ISOBMFF (ISO 14496-12:2015) § 8.11.4 - primary_item: AvifItem, - /// Associated alpha channel for the primary item, if any - alpha_item: Option, - /// If true, divide RGB values by the alpha value. - /// See `prem` in MIAF (ISO 23000-22:2019) § 7.3.5.2 - pub premultiplied_alpha: bool, + /// The collected data indicated by the `pitm` box, See ISO 14496-12:2015 § 8.11.4 + pub primary_item: TryVec, } impl AvifContext { - pub fn primary_item(&self) -> &[u8] { - self.item_as_slice(&self.primary_item) + pub fn new() -> Self { + Default::default() } - - pub fn alpha_item(&self) -> Option<&[u8]> { - self.alpha_item - .as_ref() - .map(|item| self.item_as_slice(item)) - } - - /// A helper for the various `AvifItem`s to expose a reference to the - /// underlying data while avoiding copies. - fn item_as_slice<'a>(&'a self, item: &'a AvifItem) -> &'a [u8] { - match item { - AvifItem::Location(extent) => { - for mdat in &self.item_storage { - if let Some(slice) = mdat.get(&extent) { - return slice; - } - } - unreachable!( - "AvifItem::Location requires the location exists in AvifContext::item_storage" - ); - } - AvifItem::Data(data) => return data.as_slice(), - } - } -} - -struct AvifMeta { - item_references: TryVec, - properties: TryVec, - primary_item_id: u32, - iloc_items: TryHashMap, } /// A Media Data Box -/// See ISOBMFF (ISO 14496-12:2015) § 8.1.1 -#[derive(Debug)] +/// See ISO 14496-12:2015 § 8.1.1 struct MediaDataBox { - /// Offset of `data` from the beginning of the "file". See ConstructionMethod::File. - /// Note: the file may not be an actual file, read_avif supports any `&mut impl Read` - /// source for input. However we try to match the terminology used in the spec. - file_offset: u64, + /// Offset of `data` from the beginning of the file. See ConstructionMethod::File + offset: u64, data: TryVec, } impl MediaDataBox { - /// Convert an absolute offset to an offset relative to the beginning of the - /// `self.data` field. Returns None if the offset would be negative. - /// - /// # Panics - /// - /// Panics if the offset would overflow a `usize`. - fn file_offset_to_data_offset(&self, offset: u64) -> Option { - let start = offset - .checked_sub(self.file_offset)? - .try_into() - .expect("usize overflow"); - Some(start) - } - - /// Return a slice from the MediaDataBox specified by the provided `extent`. - /// Returns `None` if the extent isn't fully contained by the MediaDataBox. - /// - /// # Panics - /// - /// Panics if either the offset or length (if the extent is bounded) of the - /// slice would overflow a `usize`. - pub fn get<'a>(&'a self, extent: &'a Extent) -> Option<&'a [u8]> { - match extent { - Extent::WithLength { offset, len } => { - let start = self.file_offset_to_data_offset(*offset)?; - let end = start.checked_add(*len).expect("usize overflow"); - self.data.get(start..end) - } - Extent::ToEnd { offset } => { - let start = self.file_offset_to_data_offset(*offset)?; - self.data.get(start..) - } - } - } -} - -#[cfg(test)] -mod media_data_box_tests { - use super::*; - - impl MediaDataBox { - fn at_offset(file_offset: u64, data: std::vec::Vec) -> Self { - MediaDataBox { - file_offset, - data: data.into(), - } + /// Check whether the beginning of `extent` is within the bounds of the `MediaDataBox`. + /// We assume extents to not cross box boundaries. If so, this will cause an error + /// in `read_extent`. + fn contains_extent(&self, extent: &ExtentRange) -> bool { + if self.offset <= extent.start() { + let start_offset = extent.start() - self.offset; + start_offset < self.data.len().to_u64() + } else { + false } } - #[test] - fn extent_with_length_before_mdat_returns_none() { - let mdat = MediaDataBox::at_offset(100, vec![1; 5]); - let extent = Extent::WithLength { offset: 0, len: 2 }; - - assert!(mdat.get(&extent).is_none()); + /// Check whether `extent` covers the `MediaDataBox` exactly. + fn matches_extent(&self, extent: &ExtentRange) -> bool { + if self.offset == extent.start() { + match extent { + ExtentRange::WithLength(range) => { + if let Some(end) = self.offset.checked_add(self.data.len().to_u64()) { + end == range.end + } else { + false + } + } + ExtentRange::ToEnd(_) => true, + } + } else { + false + } } - #[test] - fn extent_to_end_before_mdat_returns_none() { - let mdat = MediaDataBox::at_offset(100, vec![1; 5]); - let extent = Extent::ToEnd { offset: 0 }; - - assert!(mdat.get(&extent).is_none()); - } - - #[test] - fn extent_with_length_crossing_front_mdat_boundary_returns_none() { - let mdat = MediaDataBox::at_offset(100, vec![1; 5]); - let extent = Extent::WithLength { offset: 99, len: 3 }; - - assert!(mdat.get(&extent).is_none()); - } - - #[test] - fn extent_with_length_which_is_subset_of_mdat() { - let mdat = MediaDataBox::at_offset(100, vec![1; 5]); - let extent = Extent::WithLength { - offset: 101, - len: 2, + /// Copy the range specified by `extent` to the end of `buf` or return an error if the range + /// is not fully contained within `MediaDataBox`. + fn read_extent(&mut self, extent: &ExtentRange, buf: &mut TryVec) -> Result<()> { + let start_offset = extent + .start() + .checked_sub(self.offset) + .expect("mdat does not contain extent"); + let slice = match extent { + ExtentRange::WithLength(range) => { + let range_len = range + .end + .checked_sub(range.start) + .expect("range start > end"); + let end = start_offset + .checked_add(range_len) + .expect("extent end overflow"); + self.data.get(start_offset.try_into()?..end.try_into()?) + } + ExtentRange::ToEnd(_) => self.data.get(start_offset.try_into()?..), }; - - assert_eq!(mdat.get(&extent), Some(&[1, 1][..])); - } - - #[test] - fn extent_to_end_which_is_subset_of_mdat() { - let mdat = MediaDataBox::at_offset(100, vec![1; 5]); - let extent = Extent::ToEnd { offset: 101 }; - - assert_eq!(mdat.get(&extent), Some(&[1, 1, 1, 1][..])); - } - - #[test] - fn extent_with_length_which_is_all_of_mdat() { - let mdat = MediaDataBox::at_offset(100, vec![1; 5]); - let extent = Extent::WithLength { - offset: 100, - len: 5, - }; - - assert_eq!(mdat.get(&extent), Some(mdat.data.as_slice())); - } - - #[test] - fn extent_to_end_which_is_all_of_mdat() { - let mdat = MediaDataBox::at_offset(100, vec![1; 5]); - let extent = Extent::ToEnd { offset: 100 }; - - assert_eq!(mdat.get(&extent), Some(mdat.data.as_slice())); - } - - #[test] - fn extent_with_length_crossing_back_mdat_boundary_returns_none() { - let mdat = MediaDataBox::at_offset(100, vec![1; 5]); - let extent = Extent::WithLength { - offset: 103, - len: 3, - }; - - assert!(mdat.get(&extent).is_none()); - } - - #[test] - fn extent_with_length_after_mdat_returns_none() { - let mdat = MediaDataBox::at_offset(100, vec![1; 5]); - let extent = Extent::WithLength { - offset: 200, - len: 2, - }; - - assert!(mdat.get(&extent).is_none()); - } - - #[test] - fn extent_to_end_after_mdat_returns_none() { - let mdat = MediaDataBox::at_offset(100, vec![1; 5]); - let extent = Extent::ToEnd { offset: 200 }; - - assert!(mdat.get(&extent).is_none()); - } - - #[test] - #[should_panic(expected = "usize overflow")] - fn extent_with_length_which_overflows_usize_panics() { - let mdat = MediaDataBox::at_offset(std::u64::MAX - 1, vec![1; 5]); - let extent = Extent::WithLength { - offset: std::u64::MAX, - len: std::usize::MAX, - }; - - mdat.get(&extent); - } - - // The end of the range would overflow `usize` if it were calculated, but - // because the range end is unbounded, we don't calculate it. - #[test] - fn extent_to_end_which_overflows_usize() { - let mdat = MediaDataBox::at_offset(std::u64::MAX - 1, vec![1; 5]); - let extent = Extent::ToEnd { - offset: std::u64::MAX, - }; - - assert_eq!(mdat.get(&extent), Some(&[1, 1, 1, 1][..])); + let slice = slice.ok_or(Error::InvalidData("extent crosses box boundary"))?; + buf.extend_from_slice(slice)?; + Ok(()) } } /// Used for 'infe' boxes within 'iinf' boxes -/// See ISOBMFF (ISO 14496-12:2015) § 8.11.6 +/// See ISO 14496-12:2015 § 8.11.6 /// Only versions {2, 3} are supported #[derive(Debug)] struct ItemInfoEntry { @@ -994,17 +829,8 @@ struct ItemInfoEntry { item_type: u32, } -/// See ISOBMFF (ISO 14496-12:2015) § 8.11.12 -#[derive(Debug)] -struct SingleItemTypeReferenceBox { - item_type: FourCC, - from_item_id: u32, - to_item_id: u32, -} - /// Potential sizes (in bytes) of variable-sized fields of the 'iloc' box -/// See ISOBMFF (ISO 14496-12:2015) § 8.11.3 -#[derive(Debug, Clone, Copy, PartialEq)] +/// See ISO 14496-12:2015 § 8.11.3 enum IlocFieldSize { Zero, Four, @@ -1055,17 +881,18 @@ impl TryFrom for IlocVersion { } /// Used for 'iloc' boxes -/// See ISOBMFF (ISO 14496-12:2015) § 8.11.3 +/// See ISO 14496-12:2015 § 8.11.3 /// `base_offset` is omitted since it is integrated into the ranges in `extents` /// `data_reference_index` is omitted, since only 0 (i.e., this file) is supported #[derive(Debug)] struct ItemLocationBoxItem { + item_id: u32, construction_method: ConstructionMethod, /// Unused for ConstructionMethod::Idat - extents: TryVec, + extents: TryVec, } -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug)] enum ConstructionMethod { File, Idat, @@ -1073,18 +900,26 @@ enum ConstructionMethod { Item, } -/// Describes a region where a item specified by an `ItemLocationBoxItem` is stored. -/// The offset is `u64` since that's the maximum possible size and since the relative -/// nature of `MediaDataBox` means this can still possibly succeed even in the case -/// that the raw value exceeds std::usize::MAX on platforms where that type is smaller -/// than u64. However, `len` is stored as a `usize` since no value larger than -/// `std::usize::MAX` can be used in a successful indexing operation in rust. /// `extent_index` is omitted since it's only used for ConstructionMethod::Item which /// is currently not implemented. #[derive(Clone, Debug)] -enum Extent { - WithLength { offset: u64, len: usize }, - ToEnd { offset: u64 }, +struct ItemLocationBoxExtent { + extent_range: ExtentRange, +} + +#[derive(Clone, Debug)] +enum ExtentRange { + WithLength(Range), + ToEnd(RangeFrom), +} + +impl ExtentRange { + fn start(&self) -> u64 { + match self { + Self::WithLength(r) => r.start, + Self::ToEnd(r) => r.start, + } + } } #[derive(Debug, PartialEq)] @@ -1182,7 +1017,7 @@ impl Track { } } -/// See ISOBMFF (ISO 14496-12:2015) § 4.2 +/// See ISO 14496-12:2015 § 4.2 struct BMFFBox<'a, T: 'a> { head: BoxHeader, content: Take<&'a mut T>, @@ -1242,6 +1077,46 @@ impl<'a, T: Read> BMFFBox<'a, T> { } } +impl<'a, T: Read + Offset> BMFFBox<'a, T> { + /// Check whether the beginning of `extent` is within the bounds of the `BMFFBox`. + /// We assume extents to not cross box boundaries. If so, this will cause an error + /// in `read_extent`. + fn contains_extent(&self, extent: &ExtentRange) -> bool { + if self.offset() <= extent.start() { + let start_offset = extent.start() - self.offset(); + start_offset < self.bytes_left() + } else { + false + } + } + + /// Read the range specified by `extent` into `buf` or return an error if the range is not + /// fully contained within the `BMFFBox`. + fn read_extent(&mut self, extent: &ExtentRange, buf: &mut TryVec) -> Result<()> { + let start_offset = extent + .start() + .checked_sub(self.offset()) + .expect("box does not contain extent"); + skip(self, start_offset)?; + match extent { + ExtentRange::WithLength(range) => { + let len = range + .end + .checked_sub(range.start) + .expect("range start > end"); + if len > self.bytes_left() { + return Err(Error::InvalidData("extent crosses box boundary")); + } + self.take(len).try_read_to_end(buf)?; + } + ExtentRange::ToEnd(_) => { + self.try_read_to_end(buf)?; + } + } + Ok(()) + } +} + impl<'a, T> Drop for BMFFBox<'a, T> { fn drop(&mut self) { if self.content.limit() > 0 { @@ -1258,7 +1133,7 @@ impl<'a, T> Drop for BMFFBox<'a, T> { /// parsers for the internal content, or to get the length to /// skip unknown or uninteresting boxes. /// -/// See ISOBMFF (ISO 14496-12:2015) § 4.2 +/// See ISO 14496-12:2015 § 4.2 fn read_box_header(src: &mut T) -> Result { let size32 = be_u32(src)?; let name = BoxType::from(be_u32(src)?); @@ -1360,14 +1235,15 @@ fn skip_box_remain(src: &mut BMFFBox) -> Result<()> { } /// Read the contents of an AVIF file -pub fn read_avif(f: &mut T) -> Result { - let _ = env_logger::try_init(); - +/// +/// Metadata is accumulated in the passed-through `AvifContext` struct, +/// which can be examined later. +pub fn read_avif(f: &mut T, context: &mut AvifContext) -> Result<()> { let mut f = OffsetReader::new(f); let mut iter = BoxIter::new(&mut f); - // 'ftyp' box must occur first; see ISOBMFF (ISO 14496-12:2015) § 4.3.1 + // 'ftyp' box must occur first; see ISO 14496-12:2015 § 4.3.1 if let Some(mut b) = iter.next_box()? { if b.head.name == BoxType::FileTypeBox { let ftyp = read_ftyp(&mut b)?; @@ -1379,25 +1255,47 @@ pub fn read_avif(f: &mut T) -> Result { } } - let mut meta = None; - let mut item_storage = TryVec::new(); + let mut read_meta = false; + let mut mdats = TryVec::new(); + let mut primary_item_extents = None; + let mut primary_item_extents_data: TryVec> = TryVec::new(); while let Some(mut b) = iter.next_box()? { - trace!("read_avif parsing {:?} box", b.head.name); match b.head.name { BoxType::MetadataBox => { - if meta.is_some() { + if read_meta { return Err(Error::InvalidData( - "There should be zero or one meta boxes per ISOBMFF (ISO 14496-12:2015) § 8.11.1.1", + "There should be zero or one meta boxes per ISO 14496-12:2015 § 8.11.1.1", )); } - meta = Some(read_avif_meta(&mut b)?); + read_meta = true; + let primary_item_loc = read_avif_meta(&mut b)?; + match primary_item_loc.construction_method { + ConstructionMethod::File => { + primary_item_extents_data + .resize_with(primary_item_loc.extents.len(), Default::default)?; + primary_item_extents = Some(primary_item_loc.extents); + } + _ => return Err(Error::Unsupported("unsupported construction_method")), + } } BoxType::MediaDataBox => { + // See ISO 14496-12:2015 § 8.1.1 + // If we know our primary item location by this point, try to read it out of this + // mdat directly and avoid a copy + if let Some(extents) = &primary_item_extents { + for (extent, data) in extents.iter().zip(primary_item_extents_data.iter_mut()) { + if b.contains_extent(&extent.extent_range) { + b.read_extent(&extent.extent_range, data)?; + } + } + } + + // Store any remaining data for potential later extraction if b.bytes_left() > 0 { - let file_offset = b.offset(); + let offset = b.offset(); let data = b.read_into_try_vec()?; - item_storage.push(MediaDataBox { file_offset, data })?; + mdats.push(MediaDataBox { offset, data })?; } } _ => skip_box_content(&mut b)?, @@ -1406,120 +1304,39 @@ pub fn read_avif(f: &mut T) -> Result { check_parser_state!(b.content); } - let meta = meta.ok_or(Error::InvalidData("missing meta"))?; - - let mut alpha_item_ids = meta - .item_references + // If the `mdat` box came before the `meta` box, we need to fill in our primary item data + let primary_item_extents = + primary_item_extents.ok_or(Error::InvalidData("primary item extents missing"))?; + for (extent, data) in primary_item_extents .iter() - // Auxiliary image for the primary image - .filter(|iref| { - iref.to_item_id == meta.primary_item_id - && iref.from_item_id != meta.primary_item_id - && iref.item_type == b"auxl" - }) - .map(|iref| iref.from_item_id) - // which has the alpha property - .filter(|&item_id| { - meta.properties.iter().any(|prop| { - prop.item_id == item_id - && match &prop.property { - ItemProperty::AuxiliaryType(urn) => { - urn.aux_type.as_slice() - == "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha".as_bytes() - } - _ => false, - } - }) - }); - let alpha_item_id = alpha_item_ids.next(); - if alpha_item_ids.next().is_some() { - return Err(Error::InvalidData("multiple alpha planes")); - } - - let premultiplied_alpha = alpha_item_id.map_or(false, |alpha_item_id| { - meta.item_references.iter().any(|iref| { - iref.from_item_id == meta.primary_item_id - && iref.to_item_id == alpha_item_id - && iref.item_type == b"prem" - }) - }); - - let mut primary_item = None; - let mut alpha_item = None; - - // store data or record location of relevant items - for (item_id, loc) in meta.iloc_items { - let item = if item_id == meta.primary_item_id { - &mut primary_item - } else if Some(item_id) == alpha_item_id { - &mut alpha_item - } else { - continue; - }; - - if loc.construction_method != ConstructionMethod::File { - return Err(Error::Unsupported("unsupported construction_method")); - } - - assert!(item.is_none()); - - // If our item is spread over multiple extents, we'll need to copy it - // into a contiguous buffer. Otherwise, we can just store the extent - // and return a pointer into the mdat later to avoid the copy. - if loc.extents.len() > 1 { - *item = Some(AvifItem::Data(TryVec::new())); - } - - for extent in loc.extents { - let mut found = false; - // try to find an mdat which contains the extent - for mdat in item_storage.iter_mut() { - if let Some(extent_slice) = mdat.get(&extent) { - match item { - None => { - trace!("Using AvifItem::Location"); - *item = Some(AvifItem::Location(extent)); - } - Some(AvifItem::Data(item_data)) => { - trace!("Using AvifItem::Data"); - item_data.extend_from_slice(extent_slice)?; - } - _ => unreachable!(), - } - found = true; - break; + .zip(primary_item_extents_data.iter_mut()) + { + if data.is_empty() { + // try to find an overlapping mdat + for mdat in mdats.iter_mut() { + if mdat.matches_extent(&extent.extent_range) { + data.append(&mut mdat.data)?; + } else if mdat.contains_extent(&extent.extent_range) { + mdat.read_extent(&extent.extent_range, data)?; } } - - if !found { - return Err(Error::InvalidData( - "iloc contains an extent that is not in any mdat", - )); - } } - - assert!(item.is_some()); } - let primary_item = - primary_item.ok_or(Error::InvalidData("Required primary item data not found"))?; + context.primary_item = primary_item_extents_data.concat()?; - // We could potentially optimize memory usage by trying to avoid reading - // or storing mdat boxes which aren't used by our API, but for now it seems - // like unnecessary complexity - Ok(AvifContext { - item_storage, - primary_item, - alpha_item, - premultiplied_alpha, - }) + if primary_item_extents_data.iter().any(TryVec::is_empty) { + Err(Error::InvalidData("Primary item data incomplete")) + } else { + Ok(()) + } } /// Parse a metadata box in the context of an AVIF /// Currently requires the primary item to be an av01 item type and generates /// an error otherwise. -/// See ISOBMFF (ISO 14496-12:2015) § 8.11.1 -fn read_avif_meta(src: &mut BMFFBox) -> Result { +/// See ISO 14496-12:2015 § 8.11.1 +fn read_avif_meta(src: &mut BMFFBox) -> Result { let version = read_fullbox_version_no_flags(src)?; if version != 0 { @@ -1529,17 +1346,14 @@ fn read_avif_meta(src: &mut BMFFBox) -> Result { let mut primary_item_id = None; let mut item_infos = None; let mut iloc_items = None; - let mut item_references = None; - let mut properties = None; let mut iter = src.box_iter(); while let Some(mut b) = iter.next_box()? { - trace!("read_avif_meta parsing {:?} box", b.head.name); match b.head.name { BoxType::ItemInfoBox => { if item_infos.is_some() { return Err(Error::InvalidData( - "There should be zero or one iinf boxes per ISOBMFF (ISO 14496-12:2015) § 8.11.6.1", + "There should be zero or one iinf boxes per ISO 14496-12:2015 § 8.11.6.1", )); } item_infos = Some(read_iinf(&mut b)?); @@ -1547,7 +1361,7 @@ fn read_avif_meta(src: &mut BMFFBox) -> Result { BoxType::ItemLocationBox => { if iloc_items.is_some() { return Err(Error::InvalidData( - "There should be zero or one iloc boxes per ISOBMFF (ISO 14496-12:2015) § 8.11.3.1", + "There should be zero or one iloc boxes per ISO 14496-12:2015 § 8.11.3.1", )); } iloc_items = Some(read_iloc(&mut b)?); @@ -1555,23 +1369,11 @@ fn read_avif_meta(src: &mut BMFFBox) -> Result { BoxType::PrimaryItemBox => { if primary_item_id.is_some() { return Err(Error::InvalidData( - "There should be zero or one pitm boxes per ISOBMFF (ISO 14496-12:2015) § 8.11.4.1", + "There should be zero or one iloc boxes per ISO 14496-12:2015 § 8.11.4.1", )); } primary_item_id = Some(read_pitm(&mut b)?); } - BoxType::ImageReferenceBox => { - if item_references.is_some() { - return Err(Error::InvalidData("There should be zero or one iref boxes")); - } - item_references = Some(read_iref(&mut b)?); - } - BoxType::ImagePropertiesBox => { - if properties.is_some() { - return Err(Error::InvalidData("There should be zero or one iprp boxes")); - } - properties = Some(read_iprp(&mut b)?); - } _ => skip_box_content(&mut b)?, } @@ -1582,9 +1384,11 @@ fn read_avif_meta(src: &mut BMFFBox) -> Result { "Required pitm box not present in meta box", ))?; - let item_infos = item_infos.ok_or(Error::InvalidData("iinf missing"))?; - - if let Some(item_info) = item_infos.iter().find(|x| x.item_id == primary_item_id) { + if let Some(item_info) = item_infos + .iter() + .flatten() + .find(|x| x.item_id == primary_item_id) + { if &item_info.item_type.to_be_bytes() != b"av01" { warn!("primary_item_id type: {}", U32BE(item_info.item_type)); return Err(Error::InvalidData("primary_item_id type is not av01")); @@ -1595,16 +1399,21 @@ fn read_avif_meta(src: &mut BMFFBox) -> Result { )); } - Ok(AvifMeta { - properties: properties.unwrap_or_default(), - item_references: item_references.unwrap_or_default(), - primary_item_id, - iloc_items: iloc_items.ok_or(Error::InvalidData("iloc missing"))?, - }) + if let Some(loc) = iloc_items + .into_iter() + .flatten() + .find(|loc| loc.item_id == primary_item_id) + { + Ok(loc) + } else { + Err(Error::InvalidData( + "primary_item_id not present in iloc box", + )) + } } /// Parse a Primary Item Box -/// See ISOBMFF (ISO 14496-12:2015) § 8.11.4 +/// See ISO 14496-12:2015 § 8.11.4 fn read_pitm(src: &mut BMFFBox) -> Result { let version = read_fullbox_version_no_flags(src)?; @@ -1618,7 +1427,7 @@ fn read_pitm(src: &mut BMFFBox) -> Result { } /// Parse an Item Information Box -/// See ISOBMFF (ISO 14496-12:2015) § 8.11.6 +/// See ISO 14496-12:2015 § 8.11.6 fn read_iinf(src: &mut BMFFBox) -> Result> { let version = read_fullbox_version_no_flags(src)?; @@ -1664,13 +1473,13 @@ impl std::fmt::Display for U32BE { } /// Parse an Item Info Entry -/// See ISOBMFF (ISO 14496-12:2015) § 8.11.6.2 +/// See ISO 14496-12:2015 § 8.11.6.2 fn read_infe(src: &mut BMFFBox) -> Result { // According to the standard, it seems the flags field should be 0, but // at least one sample AVIF image has a nonzero value. let (version, _) = read_fullbox_extra(src)?; - // mif1 brand (see HEIF (ISO 23008-12:2017) § 10.2.1) only requires v2 and 3 + // mif1 brand (see ISO 23008-12:2017 § 10.2.1) only requires v2 and 3 let item_id = match version { 2 => be_u16(src)?.into(), 3 => be_u32(src)?, @@ -1694,432 +1503,9 @@ fn read_infe(src: &mut BMFFBox) -> Result { Ok(ItemInfoEntry { item_id, item_type }) } -/// Parse an Item Reference Box -/// See ISOBMFF (ISO 14496-12:2015) § 8.11.12 -fn read_iref(src: &mut BMFFBox) -> Result> { - let mut item_references = TryVec::new(); - let version = read_fullbox_version_no_flags(src)?; - if version > 1 { - return Err(Error::Unsupported("iref version")); - } - - let mut iter = src.box_iter(); - while let Some(mut b) = iter.next_box()? { - trace!("read_iref parsing {:?} referenceType", b.head.name); - let from_item_id = if version == 0 { - be_u16(&mut b)?.into() - } else { - be_u32(&mut b)? - }; - let reference_count = be_u16(&mut b)?; - item_references.reserve(reference_count.to_usize())?; - for _ in 0..reference_count { - let to_item_id = if version == 0 { - be_u16(&mut b)?.into() - } else { - be_u32(&mut b)? - }; - if from_item_id == to_item_id { - return Err(Error::InvalidData( - "from_item_id and to_item_id must be different", - )); - } - item_references.push(SingleItemTypeReferenceBox { - item_type: b.head.name.into(), - from_item_id, - to_item_id, - })?; - } - check_parser_state!(b.content); - } - Ok(item_references) -} - -/// Parse an Item Properties Box -/// See HEIF (ISO 23008-12:2017) § 9.3.1 -fn read_iprp(src: &mut BMFFBox) -> Result> { - let mut iter = src.box_iter(); - - let mut properties = match iter.next_box()? { - Some(mut b) if b.head.name == BoxType::ItemPropertyContainerBox => read_ipco(&mut b), - Some(_) => Err(Error::InvalidData("unexpected iprp child")), - None => Err(Error::UnexpectedEOF), - }?; - - // Per HEIF (ISO 23008-12:2017) § 9.3.1: There can be zero or more ipma boxes - // but "There shall be at most one ItemPropertyAssociationbox with a given - // pair of values of version and flags" - let mut ipma_version_and_flag_values_seen = TryVec::with_capacity(1)?; - let mut associated = TryVec::new(); - - while let Some(mut b) = iter.next_box()? { - if b.head.name != BoxType::ItemPropertyAssociationBox { - return Err(Error::InvalidData("unexpected iprp child")); - } - - let (version, flags) = read_fullbox_extra(&mut b)?; - if ipma_version_and_flag_values_seen.contains(&(version, flags)) { - return Err(Error::InvalidData("Duplicate ipma with same version/flags")); - } - if flags != 0 && properties.len() <= 127 { - return Err(Error::InvalidData("flags should be equal to 0 unless there are more than 127 properties in the ItemPropertyContainerBox")); - } - ipma_version_and_flag_values_seen.push((version, flags))?; - let associations = read_ipma(&mut b, version, flags)?; - for a in associations { - if a.property_index == 0 { - if a.essential { - return Err(Error::InvalidData("0 property index can't be essential")); - } - continue; - } - - if let Some(property) = properties.remove(&a.property_index) { - associated.push(AssociatedProperty { - item_id: a.item_id, - property, - })?; - } - } - - check_parser_state!(b.content); - } - - Ok(associated) -} - -/// See HEIF (ISO 23008-12:2017) § 9.3.1 -#[derive(Debug, PartialEq)] -pub enum ItemProperty { - Channels(TryVec), - AuxiliaryType(AuxiliaryTypeProperty), -} - -/// For storing ItemPropertyAssociation data -/// See HEIF (ISO 23008-12:2017) § 9.3.1 -struct Association { - item_id: u32, - essential: bool, - property_index: u16, -} - -/// For storing ItemPropertiesBox data -/// See HEIF (ISO 23008-12:2017) § 9.3.1 -pub struct AssociatedProperty { - pub item_id: u32, - pub property: ItemProperty, -} - -/// An upper bound which can be used to check overflow at compile time -trait UpperBounded { - const MAX: u64; -} - -/// Implement type $name as a newtype wrapper around an unsigned int which -/// implements the UpperBounded trait. -macro_rules! impl_bounded { - ( $name:ident, $inner:ty ) => { - #[derive(Clone, Copy)] - pub struct $name($inner); - - impl $name { - pub const fn new(n: $inner) -> Self { - Self(n) - } - - #[allow(dead_code)] - pub fn get(self) -> $inner { - self.0 - } - } - - impl UpperBounded for $name { - const MAX: u64 = <$inner>::MAX as u64; - } - }; -} - -/// Implement type $name as a type representing the product of two unsigned ints -/// which implements the UpperBounded trait. -macro_rules! impl_bounded_product { - ( $name:ident, $multiplier:ty, $multiplicand:ty, $inner:ty) => { - #[derive(Clone, Copy)] - pub struct $name($inner); - - impl $name { - pub fn new(value: $inner) -> Self { - assert!(<$inner>::from(value) <= Self::MAX); - Self(value) - } - - pub fn get(self) -> $inner { - self.0 - } - } - - impl UpperBounded for $name { - const MAX: u64 = <$multiplier>::MAX * <$multiplicand>::MAX; - } - }; -} - -mod bounded_uints { - use UpperBounded; - - impl_bounded!(U8, u8); - impl_bounded!(U16, u16); - impl_bounded!(U32, u32); - impl_bounded!(U64, u64); - - impl_bounded_product!(U32MulU8, U32, U8, u64); - impl_bounded_product!(U32MulU16, U32, U16, u64); - - impl UpperBounded for std::num::NonZeroU8 { - const MAX: u64 = u8::MAX as u64; - } -} - -use bounded_uints::*; - -/// Implement the multiplication operator for $lhs * $rhs giving $output, which -/// is internally represented as $inner. The operation is statically checked -/// to ensure the product won't overflow $inner, nor exceed <$output>::MAX. -macro_rules! impl_mul { - ( ($lhs:ty , $rhs:ty) => ($output:ty, $inner:ty) ) => { - impl std::ops::Mul<$rhs> for $lhs { - type Output = $output; - - fn mul(self, rhs: $rhs) -> Self::Output { - static_assertions::const_assert!(<$output>::MAX <= <$inner>::MAX as u64); - static_assertions::const_assert!(<$lhs>::MAX * <$rhs>::MAX <= <$output>::MAX); - - let lhs: $inner = self.get().into(); - let rhs: $inner = rhs.get().into(); - Self::Output::new(lhs.checked_mul(rhs).expect("infallible")) - } - } - }; -} - -impl_mul!((U8, std::num::NonZeroU8) => (U16, u16)); -impl_mul!((U32, std::num::NonZeroU8) => (U32MulU8, u64)); -impl_mul!((U32, U16) => (U32MulU16, u64)); - -impl std::ops::Add for U32MulU8 { - type Output = U64; - - fn add(self, rhs: U32MulU16) -> Self::Output { - static_assertions::const_assert!(U32MulU8::MAX + U32MulU16::MAX < U64::MAX); - let lhs: u64 = self.get().into(); - let rhs: u64 = rhs.get().into(); - Self::Output::new(lhs.checked_add(rhs).expect("infallible")) - } -} - -const MAX_IPMA_ASSOCIATION_COUNT: U8 = U8::new(u8::MAX); - -/// After reading only the `entry_count` field of an ipma box, we can check its -/// basic validity and calculate (assuming validity) the number of associations -/// which will be contained (allowing preallocation of the storage). -/// All the arithmetic is compile-time verified to not overflow via supporting -/// types implementing the UpperBounded trait. Types are declared explicitly to -/// show there isn't any accidental inference to primitive types. -/// -/// See HEIF (ISO 23008-12:2017) § 9.3.1 -fn calculate_ipma_total_associations( - version: u8, - bytes_left: u64, - entry_count: U32, - num_association_bytes: std::num::NonZeroU8, -) -> Result { - let min_entry_bytes = - std::num::NonZeroU8::new(1 /* association_count */ + if version == 0 { 2 } else { 4 }) - .unwrap(); - - let total_non_association_bytes: U32MulU8 = entry_count * min_entry_bytes; - let total_association_bytes: u64; - - if let Some(difference) = bytes_left.checked_sub(total_non_association_bytes.get()) { - // All the storage for the `essential` and `property_index` parts (assuming a valid ipma box size) - total_association_bytes = difference; - } else { - return Err(Error::InvalidData( - "ipma box below minimum size for entry_count", - )); - } - - let max_association_bytes_per_entry: U16 = MAX_IPMA_ASSOCIATION_COUNT * num_association_bytes; - let max_total_association_bytes: U32MulU16 = entry_count * max_association_bytes_per_entry; - let max_bytes_left: U64 = total_non_association_bytes + max_total_association_bytes; - - if bytes_left > max_bytes_left.get() { - return Err(Error::InvalidData( - "ipma box exceeds maximum size for entry_count", - )); - } - - let total_associations: u64 = total_association_bytes / u64::from(num_association_bytes.get()); - - Ok(total_associations.try_into()?) -} - -/// Parse an ItemPropertyAssociation box -/// See HEIF (ISO 23008-12:2017) § 9.3.1 -fn read_ipma( - src: &mut BMFFBox, - version: u8, - flags: u32, -) -> Result> { - let entry_count = be_u32(src)?; - let num_association_bytes = - std::num::NonZeroU8::new(if flags & 1 == 1 { 2 } else { 1 }).unwrap(); - - let total_associations = calculate_ipma_total_associations( - version, - src.bytes_left(), - U32::new(entry_count), - num_association_bytes, - )?; - let mut associations = TryVec::::with_capacity(total_associations)?; - - for _ in 0..entry_count { - let item_id = if version == 0 { - be_u16(src)?.into() - } else { - be_u32(src)? - }; - - if let Some(previous_association) = associations.last() { - if previous_association.item_id > item_id { - return Err(Error::InvalidData( - "Each ItemPropertyAssociation box shall be ordered by increasing item_ID", - )); - } else if previous_association.item_id == item_id { - return Err(Error::InvalidData("There shall be at most one association box for each item_ID, in any ItemPropertyAssociation box")); - } - } - - let association_count = src.read_u8()?; - for _ in 0..association_count { - let association = src - .take(num_association_bytes.get().into()) - .read_into_try_vec()?; - let mut association = BitReader::new(association.as_slice()); - let essential = association.read_bool()?; - let property_index = association.read_u16(association.remaining().try_into()?)?; - associations.push(Association { - item_id, - essential, - property_index, - })?; - } - } - - check_parser_state!(src.content); - - if version != 0 { - if let Some(Association { - item_id: max_item_id, - .. - }) = associations.last() - { - if *max_item_id <= u16::MAX.into() { - return Err(Error::InvalidData( - "The version 0 should be used unless 32-bit item_ID values are needed", - )); - } - } - } - - Ok(associations) -} - -/// Parse an ItemPropertyContainerBox -/// See HEIF (ISO 23008-12:2017) § 9.3.1 -fn read_ipco(src: &mut BMFFBox) -> Result> { - let mut properties = TryHashMap::with_capacity(1)?; - - let mut index: u16 = 1; // ipma uses 1-based indexing - let mut iter = src.box_iter(); - while let Some(mut b) = iter.next_box()? { - if let Some(property) = match b.head.name { - BoxType::PixelInformationBox => Some(ItemProperty::Channels(read_pixi(&mut b)?)), - BoxType::AuxiliaryTypeProperty => Some(ItemProperty::AuxiliaryType(read_auxc(&mut b)?)), - _ => { - skip_box_remain(&mut b)?; - None - } - } { - properties.insert(index, property)?; - } - - index = index - .checked_add(1) // must include ignored properties to have correct indexes - .ok_or(Error::InvalidData("ipco index overflow"))?; - - check_parser_state!(b.content); - } - - Ok(properties) -} - -/// Parse pixel information -/// See HEIF (ISO 23008-12:2017) § 6.5.6 -fn read_pixi(src: &mut BMFFBox) -> Result> { - let version = read_fullbox_version_no_flags(src)?; - if version != 0 { - return Err(Error::Unsupported("pixi version")); - } - - let num_channels = src.read_u8()?.into(); - let mut channels = TryVec::with_capacity(num_channels)?; - let num_channels_read = src.try_read_to_end(&mut channels)?; - - if num_channels_read != num_channels.into() { - return Err(Error::InvalidData("invalid num_channels")); - } - - check_parser_state!(src.content); - Ok(channels) -} - -/// See HEIF (ISO 23008-12:2017) § 6.5.8 -#[derive(Debug, PartialEq)] -pub struct AuxiliaryTypeProperty { - aux_type: TryString, - aux_subtype: TryString, -} - -/// Parse image properties for auxiliary images -/// See HEIF (ISO 23008-12:2017) § 6.5.8 -fn read_auxc(src: &mut BMFFBox) -> Result { - let version = read_fullbox_version_no_flags(src)?; - if version != 0 { - return Err(Error::Unsupported("auxC version")); - } - - let mut aux = TryString::new(); - src.try_read_to_end(&mut aux)?; - - let (aux_type, aux_subtype): (TryString, TryVec); - if let Some(nul_byte_pos) = aux.iter().position(|&b| b == b'\0') { - let (a, b) = aux.as_slice().split_at(nul_byte_pos); - aux_type = a.try_into()?; - aux_subtype = (&b[1..]).try_into()?; - } else { - aux_type = aux; - aux_subtype = TryVec::new(); - } - - Ok(AuxiliaryTypeProperty { - aux_type, - aux_subtype, - }) -} - /// Parse an item location box inside a meta box -/// See ISOBMFF (ISO 14496-12:2015) § 8.11.3 -fn read_iloc(src: &mut BMFFBox) -> Result> { +/// See ISO 14496-12:2015 § 8.11.3 +fn read_iloc(src: &mut BMFFBox) -> Result> { let version: IlocVersion = read_fullbox_version_no_flags(src)?.try_into()?; let iloc = src.read_into_try_vec()?; @@ -2142,7 +1528,7 @@ fn read_iloc(src: &mut BMFFBox) -> Result iloc.read_u32(32)?, }; - let mut items = TryHashMap::with_capacity(item_count.to_usize())?; + let mut items = TryVec::with_capacity(item_count.to_usize())?; for _ in 0..item_count { let item_id = match version { @@ -2163,7 +1549,7 @@ fn read_iloc(src: &mut BMFFBox) -> Result ConstructionMethod::File, 1 => ConstructionMethod::Idat, 2 => return Err(Error::Unsupported("construction_method 'item_offset' is not supported")), - _ => return Err(Error::InvalidData("construction_method is taken from the set 0, 1 or 2 per ISOBMFF (ISO 14496-12:2015) § 8.11.3.3")) + _ => return Err(Error::InvalidData("construction_method is taken from the set 0, 1 or 2 per ISO 14496-12:2015 § 8.11.3.3")) } } }; @@ -2181,24 +1567,14 @@ fn read_iloc(src: &mut BMFFBox) -> Result None, Some(index_size) => { @@ -2207,38 +1583,35 @@ fn read_iloc(src: &mut BMFFBox) -> Result 0. let extent_offset = iloc.read_u64(offset_size.to_bits())?; - let extent_length = iloc.read_u64(length_size.to_bits())?.try_into()?; + let extent_length = iloc.read_u64(length_size.to_bits())?; // "If the length is not specified, or specified as zero, then the entire length of // the source is implied" (ibid) - let offset = base_offset + let start = base_offset .checked_add(extent_offset) .ok_or(Error::InvalidData("offset calculation overflow"))?; - let extent = if extent_length == 0 { - Extent::ToEnd { offset } + let extent_range = if extent_length == 0 { + ExtentRange::ToEnd(RangeFrom { start }) } else { - Extent::WithLength { - offset, - len: extent_length, - } + let end = start + .checked_add(extent_length) + .ok_or(Error::InvalidData("end calculation overflow"))?; + ExtentRange::WithLength(Range { start, end }) }; - extents.push(extent)?; + extents.push(ItemLocationBoxExtent { extent_range })?; } - let loc = ItemLocationBoxItem { + items.push(ItemLocationBoxItem { + item_id, construction_method, extents, - }; - - if items.insert(item_id, loc)?.is_some() { - return Err(Error::InvalidData("duplicate item_ID in iloc")); - } + })?; } if iloc.remaining() == 0 { @@ -2249,9 +1622,12 @@ fn read_iloc(src: &mut BMFFBox) -> Result(f: &mut T) -> Result { - let mut context = None; +/// +/// Metadata is accumulated in the passed-through `MediaContext` struct, +/// which can be examined later. +pub fn read_mp4(f: &mut T, context: &mut MediaContext) -> Result<()> { let mut found_ftyp = false; + let mut found_moov = false; // TODO(kinetik): Top-level parsing should handle zero-sized boxes // rather than throwing an error. let mut iter = BoxIter::new(f); @@ -2278,12 +1654,13 @@ pub fn read_mp4(f: &mut T) -> Result { debug!("{:?}", ftyp); } BoxType::MovieBox => { - context = Some(read_moov(&mut b)?); + read_moov(&mut b, context)?; + found_moov = true; } _ => skip_box_content(&mut b)?, }; check_parser_state!(b.content); - if context.is_some() { + if found_moov { debug!( "found moov {}, could stop pure 'moov' parser now", if found_ftyp { @@ -2298,64 +1675,56 @@ pub fn read_mp4(f: &mut T) -> Result { // XXX(kinetik): This isn't perfect, as a "moov" with no contents is // treated as okay but we haven't found anything useful. Needs more // thought for clearer behaviour here. - context.ok_or(Error::NoMoov) + if found_moov { + Ok(()) + } else { + Err(Error::NoMoov) + } } -fn parse_mvhd(f: &mut BMFFBox) -> Result> { +fn parse_mvhd(f: &mut BMFFBox) -> Result<(MovieHeaderBox, Option)> { let mvhd = read_mvhd(f)?; - debug!("{:?}", mvhd); if mvhd.timescale == 0 { return Err(Error::InvalidData("zero timescale in mdhd")); } let timescale = Some(MediaTimeScale(u64::from(mvhd.timescale))); - Ok(timescale) + Ok((mvhd, timescale)) } -fn read_moov(f: &mut BMFFBox) -> Result { - let MediaContext { - mut timescale, - mut tracks, - mut mvex, - mut psshs, - mut userdata, - } = Default::default(); - +fn read_moov(f: &mut BMFFBox, context: &mut MediaContext) -> Result<()> { let mut iter = f.box_iter(); while let Some(mut b) = iter.next_box()? { match b.head.name { BoxType::MovieHeaderBox => { - timescale = parse_mvhd(&mut b)?; + let (mvhd, timescale) = parse_mvhd(&mut b)?; + context.timescale = timescale; + debug!("{:?}", mvhd); } BoxType::TrackBox => { - let mut track = Track::new(tracks.len()); + let mut track = Track::new(context.tracks.len()); read_trak(&mut b, &mut track)?; - tracks.push(track)?; + context.tracks.push(track)?; } BoxType::MovieExtendsBox => { - mvex = Some(read_mvex(&mut b)?); + let mvex = read_mvex(&mut b)?; debug!("{:?}", mvex); + context.mvex = Some(mvex); } BoxType::ProtectionSystemSpecificHeaderBox => { let pssh = read_pssh(&mut b)?; debug!("{:?}", pssh); - psshs.push(pssh)?; + context.psshs.push(pssh)?; } BoxType::UserdataBox => { - userdata = Some(read_udta(&mut b)); - debug!("{:?}", userdata); + let udta = read_udta(&mut b); + debug!("{:?}", udta); + context.userdata = Some(udta); } _ => skip_box_content(&mut b)?, }; check_parser_state!(b.content); } - - Ok(MediaContext { - timescale, - tracks, - mvex, - psshs, - userdata, - }) + Ok(()) } fn read_pssh(src: &mut BMFFBox) -> Result { @@ -2595,7 +1964,7 @@ fn read_stbl(f: &mut BMFFBox, track: &mut Track) -> Result<()> { } /// Parse an ftyp box. -/// See ISOBMFF (ISO 14496-12:2015) § 4.3 +/// See ISO 14496-12:2015 § 4.3 fn read_ftyp(src: &mut BMFFBox) -> Result { let major = be_u32(src)?; let minor = be_u32(src)?; @@ -2701,7 +2070,7 @@ fn read_tkhd(src: &mut BMFFBox) -> Result { } /// Parse a elst box. -/// See ISOBMFF (ISO 14496-12:2015) § 8.6.6 +/// See ISO 14496-12:2015 § 8.6.6 fn read_elst(src: &mut BMFFBox) -> Result { let (version, _) = read_fullbox_extra(src)?; let edit_count = be_u32_with_limit(src)?; @@ -2777,7 +2146,7 @@ fn read_mdhd(src: &mut BMFFBox) -> Result { } /// Parse a stco box. -/// See ISOBMFF (ISO 14496-12:2015) § 8.7.5 +/// See ISO 14496-12:2015 § 8.7.5 fn read_stco(src: &mut BMFFBox) -> Result { let (_, _) = read_fullbox_extra(src)?; let offset_count = be_u32_with_limit(src)?; @@ -2793,7 +2162,7 @@ fn read_stco(src: &mut BMFFBox) -> Result { } /// Parse a co64 box. -/// See ISOBMFF (ISO 14496-12:2015) § 8.7.5 +/// See ISO 14496-12:2015 § 8.7.5 fn read_co64(src: &mut BMFFBox) -> Result { let (_, _) = read_fullbox_extra(src)?; let offset_count = be_u32_with_limit(src)?; @@ -2809,7 +2178,7 @@ fn read_co64(src: &mut BMFFBox) -> Result { } /// Parse a stss box. -/// See ISOBMFF (ISO 14496-12:2015) § 8.6.2 +/// See ISO 14496-12:2015 § 8.6.2 fn read_stss(src: &mut BMFFBox) -> Result { let (_, _) = read_fullbox_extra(src)?; let sample_count = be_u32_with_limit(src)?; @@ -2825,7 +2194,7 @@ fn read_stss(src: &mut BMFFBox) -> Result { } /// Parse a stsc box. -/// See ISOBMFF (ISO 14496-12:2015) § 8.7.4 +/// See ISO 14496-12:2015 § 8.7.4 fn read_stsc(src: &mut BMFFBox) -> Result { let (_, _) = read_fullbox_extra(src)?; let sample_count = be_u32_with_limit(src)?; @@ -2848,7 +2217,7 @@ fn read_stsc(src: &mut BMFFBox) -> Result { } /// Parse a Composition Time to Sample Box -/// See ISOBMFF (ISO 14496-12:2015) § 8.6.1.3 +/// See ISO 14496-12:2015 § 8.6.1.3 fn read_ctts(src: &mut BMFFBox) -> Result { let (version, _) = read_fullbox_extra(src)?; @@ -2890,7 +2259,7 @@ fn read_ctts(src: &mut BMFFBox) -> Result { } /// Parse a stsz box. -/// See ISOBMFF (ISO 14496-12:2015) § 8.7.3.2 +/// See ISO 14496-12:2015 § 8.7.3.2 fn read_stsz(src: &mut BMFFBox) -> Result { let (_, _) = read_fullbox_extra(src)?; let sample_size = be_u32(src)?; @@ -2913,7 +2282,7 @@ fn read_stsz(src: &mut BMFFBox) -> Result { } /// Parse a stts box. -/// See ISOBMFF (ISO 14496-12:2015) § 8.6.1.2 +/// See ISO 14496-12:2015 § 8.6.1.2 fn read_stts(src: &mut BMFFBox) -> Result { let (_, _) = read_fullbox_extra(src)?; let sample_count = be_u32_with_limit(src)?; @@ -3065,7 +2434,7 @@ fn read_flac_metadata(src: &mut BMFFBox) -> Result Result<()> { // Tags for elementary stream description const ESDESCR_TAG: u8 = 0x03; @@ -3079,7 +2448,7 @@ fn find_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { let des = &mut Cursor::new(remains); let tag = des.read_u8()?; - // See MPEG-4 Systems (ISO 14496-1:2010) § 8.3.3 for interpreting size of expandable classes + // See ISO 14496-1:2010 § 8.3.3 for interpreting size of expandable classes let mut end: u32 = 0; // It's u8 without declaration type that is incorrect. // MSB of extend_or_len indicates more bytes, up to 4 bytes. @@ -3137,7 +2506,7 @@ fn get_audio_object_type(bit_reader: &mut BitReader) -> Result { Ok(audio_object_type) } -/// See MPEG-4 Systems (ISO 14496-1:2010) § 7.2.6.7 and probably 14496-3 somewhere? +/// See ISO 14496-1:2010 § 7.2.6.7 and probably 14496-3 somewhere? fn read_ds_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { let frequency_table = vec![ (0x0, 96000), @@ -3308,7 +2677,7 @@ fn read_surround_channel_count(bit_reader: &mut BitReader, channels: u8) -> Resu Ok(count) } -/// See MPEG-4 Systems (ISO 14496-1:2010) § 7.2.6.6 +/// See ISO 14496-1:2010 § 7.2.6.6 fn read_dc_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { let des = &mut Cursor::new(data); let object_profile = des.read_u8()?; @@ -3329,7 +2698,7 @@ fn read_dc_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { Ok(()) } -/// See MPEG-4 Systems (ISO 14496-1:2010) § 7.2.6.5 +/// See ISO 14496-1:2010 § 7.2.6.5 fn read_es_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { let des = &mut Cursor::new(data); @@ -3357,7 +2726,7 @@ fn read_es_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> { Ok(()) } -/// See MP4 (ISO 14496-14:2020) § 6.7.2 +/// See ISO 14496-14:2010 § 6.7.2 fn read_esds(src: &mut BMFFBox) -> Result { let (_, _) = read_fullbox_extra(src)?; @@ -3665,7 +3034,7 @@ fn read_qt_wave_atom(src: &mut BMFFBox) -> Result { } /// Parse an audio description inside an stsd box. -/// See ISOBMFF (ISO 14496-12:2015) § 12.2.3 +/// See ISO 14496-12:2015 § 12.2.3 fn read_audio_sample_entry(src: &mut BMFFBox) -> Result { let name = src.get_header().name; @@ -3798,8 +3167,8 @@ fn read_audio_sample_entry(src: &mut BMFFBox) -> Result } /// Parse a stsd box. -/// See ISOBMFF (ISO 14496-12:2015) § 8.5.2 -/// See MP4 (ISO 14496-14:2020) § 6.7.2 +/// See ISO 14496-12:2015 § 8.5.2 +/// See ISO 14496-14:2010 § 6.7.2 fn read_stsd(src: &mut BMFFBox, track: &mut Track) -> Result { let (_, _) = read_fullbox_extra(src)?; diff --git a/third_party/rust/mp4parse/src/tests.rs b/third_party/rust/mp4parse/src/tests.rs index 37642ac37386..2f1765730f5b 100644 --- a/third_party/rust/mp4parse/src/tests.rs +++ b/third_party/rust/mp4parse/src/tests.rs @@ -7,6 +7,7 @@ use super::read_mp4; use super::Error; +use super::MediaContext; use fallible_collections::TryRead as _; use std::convert::TryInto as _; @@ -194,7 +195,8 @@ fn read_truncated_ftyp() { .B32(0) // minor version .append_bytes(b"isom") }); - match read_mp4(&mut stream) { + let mut context = MediaContext::new(); + match read_mp4(&mut stream, &mut context) { Err(Error::UnexpectedEOF) => (), Ok(_) => panic!("expected an error result"), _ => panic!("expected a different error result"), @@ -344,7 +346,7 @@ fn read_mdhd_invalid_timescale() { assert_eq!(stream.head.name, BoxType::MediaHeaderBox); assert_eq!(stream.head.size, 44); let r = super::parse_mdhd(&mut stream, &mut super::Track::new(0)); - assert!(r.is_err()); + assert_eq!(r.is_err(), true); } #[test] @@ -385,7 +387,7 @@ fn read_mvhd_invalid_timescale() { assert_eq!(stream.head.name, BoxType::MovieHeaderBox); assert_eq!(stream.head.size, 120); let r = super::parse_mvhd(&mut stream); - assert!(r.is_err()); + assert_eq!(r.is_err(), true); } #[test] @@ -1247,8 +1249,9 @@ fn read_invalid_pssh() { let mut stream = make_box(BoxSize::Auto, b"moov", |s| s.append_bytes(pssh.as_slice())); let mut iter = super::BoxIter::new(&mut stream); let mut stream = iter.next_box().unwrap().unwrap(); + let mut context = super::MediaContext::new(); - match super::read_moov(&mut stream) { + match super::read_moov(&mut stream, &mut context) { Err(Error::InvalidData(s)) => assert_eq!(s, "read_buf size exceeds BUF_SIZE_LIMIT"), _ => panic!("unexpected result with invalid descriptor"), } diff --git a/third_party/rust/mp4parse/tests/corrupt/bug-1655846.avif b/third_party/rust/mp4parse/tests/bug-1655846.avif similarity index 100% rename from third_party/rust/mp4parse/tests/corrupt/bug-1655846.avif rename to third_party/rust/mp4parse/tests/bug-1655846.avif diff --git a/third_party/rust/mp4parse/tests/bug-1661347.avif b/third_party/rust/mp4parse/tests/bug-1661347.avif index 00ef35bf74a3..11b539230bb4 100644 Binary files a/third_party/rust/mp4parse/tests/bug-1661347.avif and b/third_party/rust/mp4parse/tests/bug-1661347.avif differ diff --git a/third_party/rust/mp4parse/tests/corrupt/bad-ipma-flags.avif b/third_party/rust/mp4parse/tests/corrupt/bad-ipma-flags.avif deleted file mode 100644 index 40012f2114aa..000000000000 Binary files a/third_party/rust/mp4parse/tests/corrupt/bad-ipma-flags.avif and /dev/null differ diff --git a/third_party/rust/mp4parse/tests/corrupt/bad-ipma-version.avif b/third_party/rust/mp4parse/tests/corrupt/bad-ipma-version.avif deleted file mode 100644 index e8442c166c78..000000000000 Binary files a/third_party/rust/mp4parse/tests/corrupt/bad-ipma-version.avif and /dev/null differ diff --git a/third_party/rust/mp4parse/tests/corrupt/bug-1661347.avif b/third_party/rust/mp4parse/tests/corrupt/bug-1661347.avif deleted file mode 100644 index 11b539230bb4..000000000000 Binary files a/third_party/rust/mp4parse/tests/corrupt/bug-1661347.avif and /dev/null differ diff --git a/third_party/rust/mp4parse/tests/kodim-extents.avif b/third_party/rust/mp4parse/tests/kodim-extents.avif deleted file mode 100644 index 12e010572010..000000000000 Binary files a/third_party/rust/mp4parse/tests/kodim-extents.avif and /dev/null differ diff --git a/third_party/rust/mp4parse/tests/public.rs b/third_party/rust/mp4parse/tests/public.rs index 817276fad301..870dc535c7ed 100644 --- a/third_party/rust/mp4parse/tests/public.rs +++ b/third_party/rust/mp4parse/tests/public.rs @@ -4,7 +4,6 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. extern crate mp4parse as mp4; -use mp4::Error; use std::convert::TryInto; use std::fs::File; use std::io::{Cursor, Read}; @@ -29,15 +28,10 @@ static AUDIO_EME_CBCS_MP4: &str = "tests/bipbop_cbcs_audio_init.mp4"; static VIDEO_EME_CBCS_MP4: &str = "tests/bipbop_cbcs_video_init.mp4"; static VIDEO_AV1_MP4: &str = "tests/tiny_av1.mp4"; static IMAGE_AVIF: &str = "av1-avif/testFiles/Microsoft/Monochrome.avif"; -static IMAGE_AVIF_EXTENTS: &str = "tests/kodim-extents.avif"; -static IMAGE_AVIF_ALPHA: &str = "tests/bug-1661347.avif"; -static IMAGE_AVIF_CORRUPT: &str = "tests/corrupt/bug-1655846.avif"; -static IMAGE_AVIF_CORRUPT_2: &str = "tests/corrupt/bug-1661347.avif"; -static IMAGE_AVIF_CORRUPT_3: &str = "tests/corrupt/bad-ipma-version.avif"; -static IMAGE_AVIF_CORRUPT_4: &str = "tests/corrupt/bad-ipma-flags.avif"; +static IMAGE_AVIF_CORRUPT: &str = "tests/bug-1655846.avif"; +static IMAGE_AVIF_CORRUPT_2: &str = "tests/bug-1661347.avif"; static IMAGE_AVIF_GRID: &str = "av1-avif/testFiles/Microsoft/Summer_in_Tomsk_720p_5x4_grid.avif"; -static AVIF_TEST_DIRS: &[&str] = &["tests", "av1-avif/testFiles"]; -static AVIF_CORRUPT_IMAGES: &str = "tests/corrupt"; +static AVIF_TEST_DIR: &str = "av1-avif/testFiles"; // Adapted from https://github.com/GuillaumeGomez/audio-video-metadata/blob/9dff40f565af71d5502e03a2e78ae63df95cfd40/src/metadata.rs#L53 #[test] @@ -48,7 +42,8 @@ fn public_api() { fd.read_to_end(&mut buf).expect("File error"); let mut c = Cursor::new(&buf); - let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); + let mut context = mp4::MediaContext::new(); + mp4::read_mp4(&mut c, &mut context).expect("read_mp4 failed"); assert_eq!(context.timescale, Some(mp4::MediaTimeScale(1000))); for track in context.tracks { match track.track_type { @@ -168,7 +163,8 @@ fn public_metadata() { fd.read_to_end(&mut buf).expect("File error"); let mut c = Cursor::new(&buf); - let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); + let mut context = mp4::MediaContext::new(); + mp4::read_mp4(&mut c, &mut context).expect("read_mp4 failed"); let udta = context .userdata .expect("didn't find udta") @@ -235,7 +231,8 @@ fn public_metadata_gnre() { fd.read_to_end(&mut buf).expect("File error"); let mut c = Cursor::new(&buf); - let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); + let mut context = mp4::MediaContext::new(); + mp4::read_mp4(&mut c, &mut context).expect("read_mp4 failed"); let udta = context .userdata .expect("didn't find udta") @@ -303,7 +300,8 @@ fn public_audio_tenc() { fd.read_to_end(&mut buf).expect("File error"); let mut c = Cursor::new(&buf); - let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); + let mut context = mp4::MediaContext::new(); + mp4::read_mp4(&mut c, &mut context).expect("read_mp4 failed"); for track in context.tracks { let stsd = track.stsd.expect("expected an stsd"); let a = match stsd.descriptions.first().expect("expected a SampleEntry") { @@ -361,7 +359,8 @@ fn public_video_cenc() { fd.read_to_end(&mut buf).expect("File error"); let mut c = Cursor::new(&buf); - let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); + let mut context = mp4::MediaContext::new(); + mp4::read_mp4(&mut c, &mut context).expect("read_mp4 failed"); for track in context.tracks { let stsd = track.stsd.expect("expected an stsd"); let v = match stsd.descriptions.first().expect("expected a SampleEntry") { @@ -433,7 +432,8 @@ fn public_audio_cbcs() { fd.read_to_end(&mut buf).expect("File error"); let mut c = Cursor::new(&buf); - let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); + let mut context = mp4::MediaContext::new(); + mp4::read_mp4(&mut c, &mut context).expect("read_mp4 failed"); for track in context.tracks { let stsd = track.stsd.expect("expected an stsd"); assert_eq!(stsd.descriptions.len(), 2); @@ -515,7 +515,8 @@ fn public_video_cbcs() { fd.read_to_end(&mut buf).expect("File error"); let mut c = Cursor::new(&buf); - let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); + let mut context = mp4::MediaContext::new(); + mp4::read_mp4(&mut c, &mut context).expect("read_mp4 failed"); for track in context.tracks { let stsd = track.stsd.expect("expected an stsd"); assert_eq!(stsd.descriptions.len(), 2); @@ -574,7 +575,8 @@ fn public_video_av1() { fd.read_to_end(&mut buf).expect("File error"); let mut c = Cursor::new(&buf); - let context = mp4::read_mp4(&mut c).expect("read_mp4 failed"); + let mut context = mp4::MediaContext::new(); + mp4::read_mp4(&mut c, &mut context).expect("read_mp4 failed"); for track in context.tracks { // track part assert_eq!(track.duration, Some(mp4::TrackScaledTime(512, 0))); @@ -620,92 +622,54 @@ fn public_video_av1() { #[test] fn public_avif_primary_item() { + let context = &mut mp4::AvifContext::new(); let input = &mut File::open(IMAGE_AVIF).expect("Unknown file"); - let context = mp4::read_avif(input).expect("read_avif failed"); - assert_eq!(context.primary_item().len(), 6979); - assert_eq!(context.primary_item()[0..4], [0x12, 0x00, 0x0a, 0x0a]); -} - -#[test] -fn public_avif_primary_item_split_extents() { - let input = &mut File::open(IMAGE_AVIF_EXTENTS).expect("Unknown file"); - let context = mp4::read_avif(input).expect("read_avif failed"); - assert_eq!(context.primary_item().len(), 4387); -} - -#[test] -fn public_avif_alpha_item() { - let input = &mut File::open(IMAGE_AVIF_ALPHA).expect("Unknown file"); - let context = mp4::read_avif(input).expect("read_avif failed"); - assert!(context.alpha_item().is_some()); - assert!(!context.premultiplied_alpha); + mp4::read_avif(input, context).expect("read_avif failed"); + assert_eq!(context.primary_item.len(), 6979); + assert_eq!(context.primary_item[0..4], [0x12, 0x00, 0x0a, 0x0a]); } #[test] fn public_avif_bug_1655846() { + let context = &mut mp4::AvifContext::new(); let input = &mut File::open(IMAGE_AVIF_CORRUPT).expect("Unknown file"); - assert!(mp4::read_avif(input).is_err()); + assert!(mp4::read_avif(input, context).is_err()); } #[test] fn public_avif_bug_1661347() { + let context = &mut mp4::AvifContext::new(); let input = &mut File::open(IMAGE_AVIF_CORRUPT_2).expect("Unknown file"); - assert!(mp4::read_avif(input).is_err()); -} - -fn assert_invalid_data(result: mp4::Result, expected_msg: &str) { - match result { - Err(Error::InvalidData(msg)) if msg == expected_msg => {} - r => panic!( - "Expected Err(Error::InvalidData({:?})), found {:?}", - expected_msg, r - ), - } -} - -#[test] -fn public_avif_bad_ipma_version() { - let input = &mut File::open(IMAGE_AVIF_CORRUPT_3).expect("Unknown file"); - let expected_msg = "The version 0 should be used unless 32-bit item_ID values are needed"; - assert_invalid_data(mp4::read_avif(input), expected_msg); -} - -#[test] -fn public_avif_bad_ipma_flags() { - let input = &mut File::open(IMAGE_AVIF_CORRUPT_4).expect("Unknown file"); - let expected_msg = "flags should be equal to 0 unless there are more than 127 properties in the ItemPropertyContainerBox"; - assert_invalid_data(mp4::read_avif(input), expected_msg); + assert!(mp4::read_avif(input, context).is_err()); } #[test] #[ignore] // Remove when we add support; see https://github.com/mozilla/mp4parse-rust/issues/198 fn public_avif_primary_item_is_grid() { + let context = &mut mp4::AvifContext::new(); let input = &mut File::open(IMAGE_AVIF_GRID).expect("Unknown file"); - mp4::read_avif(input).expect("read_avif failed"); + mp4::read_avif(input, context).expect("read_avif failed"); // Add some additional checks } #[test] fn public_avif_read_samples() { - for dir in AVIF_TEST_DIRS { - for entry in walkdir::WalkDir::new(dir) { - let entry = entry.expect("AVIF entry"); - let path = entry.path(); - if !path.is_file() || path.extension().unwrap_or_default() != "avif" { - eprintln!("Skipping {:?}", path); - continue; // Skip directories, ReadMe.txt, etc. - } - if path.parent().unwrap() == Path::new(AVIF_CORRUPT_IMAGES) { - eprintln!("Skipping {:?}", path); - continue; - } - if path == Path::new(IMAGE_AVIF_GRID) { - eprintln!("Skipping {:?}", path); - continue; // Remove when public_avif_primary_item_is_grid passes - } - println!("parsing {:?}", path); - let input = &mut File::open(path).expect("Unknow file"); - mp4::read_avif(input).expect("read_avif failed"); + env_logger::init(); + + for entry in walkdir::WalkDir::new(AVIF_TEST_DIR) { + let entry = entry.expect("AVIF entry"); + let path = entry.path(); + if !path.is_file() || path.extension().unwrap_or_default() != "avif" { + eprintln!("Skipping {:?}", path); + continue; // Skip directories, ReadMe.txt, etc. } + if path == Path::new(IMAGE_AVIF_GRID) { + eprintln!("Skipping {:?}", path); + continue; // Remove when public_avif_primary_item_is_grid passes + } + println!("parsing {:?}", path); + let context = &mut mp4::AvifContext::new(); + let input = &mut File::open(path).expect("Unknow file"); + mp4::read_avif(input, context).expect("read_avif failed"); } } diff --git a/third_party/rust/mp4parse_capi/.cargo-checksum.json b/third_party/rust/mp4parse_capi/.cargo-checksum.json index e59d87b75456..675d67fa370a 100644 --- a/third_party/rust/mp4parse_capi/.cargo-checksum.json +++ b/third_party/rust/mp4parse_capi/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"ba144343a4d38fe6918dd61bb6723e46ac297f506a27370c1d10b49bd8123572","cbindgen.toml":"5c9429f271d6e914d81b63e6509c04ffe84cab11ed3a53a2ed4715e5d5ace80e","examples/dump.rs":"83462422315c22e496960bae922edb23105c0aa272d2b106edd7574ff068513a","src/lib.rs":"d25c2e010186ada3524801e8f1ecdbe42cc4f961880ccca11ba9bdddd42363f7","tests/test_chunk_out_of_range.rs":"b5da583218d98027ed973a29c67434a91a1306f2d2fb39ec4d640d4824c308ce","tests/test_encryption.rs":"ca98516ff423c03b5fcc17b05f993f13b32485e4cf3ba86faf1bea72681d75ce","tests/test_fragment.rs":"e90eb5a4418d30002655466c0c4b3125c7fd70a74b6871471eaa172f1def9db8","tests/test_rotation.rs":"fb43c2f2dfa496d151c33bdd46c0fd3252387c23cc71e2cac9ed0234de715a81","tests/test_sample_table.rs":"185755909b2f4e0ea99604bb423a07623d614a180accdaebd1c98aef2c2e3ae6","tests/test_workaround_stsc.rs":"7dd419f3d55b9a3a039cac57e58a9240a9c8166bcd4356c24f69f731c3ced83b"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"87fce2f5e05b37d95cf255301762ea20d08a772112da2ade46eb39a76e8d27e0","cbindgen.toml":"5c9429f271d6e914d81b63e6509c04ffe84cab11ed3a53a2ed4715e5d5ace80e","examples/dump.rs":"83462422315c22e496960bae922edb23105c0aa272d2b106edd7574ff068513a","src/lib.rs":"76fb7cd35bbe56463d43f452fd7ebaf5b4619bd661fb71fb45f69e980877b424","tests/test_chunk_out_of_range.rs":"b5da583218d98027ed973a29c67434a91a1306f2d2fb39ec4d640d4824c308ce","tests/test_encryption.rs":"ca98516ff423c03b5fcc17b05f993f13b32485e4cf3ba86faf1bea72681d75ce","tests/test_fragment.rs":"e90eb5a4418d30002655466c0c4b3125c7fd70a74b6871471eaa172f1def9db8","tests/test_rotation.rs":"fb43c2f2dfa496d151c33bdd46c0fd3252387c23cc71e2cac9ed0234de715a81","tests/test_sample_table.rs":"185755909b2f4e0ea99604bb423a07623d614a180accdaebd1c98aef2c2e3ae6","tests/test_workaround_stsc.rs":"7dd419f3d55b9a3a039cac57e58a9240a9c8166bcd4356c24f69f731c3ced83b"},"package":null} \ No newline at end of file diff --git a/third_party/rust/mp4parse_capi/Cargo.toml b/third_party/rust/mp4parse_capi/Cargo.toml index b4ede98c93e7..e46cccde7c5d 100644 --- a/third_party/rust/mp4parse_capi/Cargo.toml +++ b/third_party/rust/mp4parse_capi/Cargo.toml @@ -24,7 +24,7 @@ travis-ci = { repository = "https://github.com/mozilla/mp4parse-rust" } [dependencies] byteorder = "1.2.1" -fallible_collections = { version = "0.3", features = ["std_io"] } +fallible_collections = { version = "0.2", features = ["std_io"] } log = "0.4" mp4parse = {version = "0.11.2", path = "../mp4parse"} num-traits = "=0.2.10" diff --git a/third_party/rust/mp4parse_capi/src/lib.rs b/third_party/rust/mp4parse_capi/src/lib.rs index becb5dec1d36..65c6df466fad 100644 --- a/third_party/rust/mp4parse_capi/src/lib.rs +++ b/third_party/rust/mp4parse_capi/src/lib.rs @@ -16,8 +16,8 @@ //! Err(_) => -1, //! } //! } -//! let capi_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); -//! let mut file = std::fs::File::open(capi_dir + "/../mp4parse/tests/minimal.mp4").unwrap(); +//! +//! let mut file = std::fs::File::open("../mp4parse/tests/minimal.mp4").unwrap(); //! let io = mp4parse_capi::Mp4parseIo { //! read: Some(buf_read), //! userdata: &mut file as *mut _ as *mut std::os::raw::c_void @@ -436,14 +436,6 @@ pub struct Mp4parseParser { video_track_sample_descriptions: TryHashMap>, } -#[repr(C)] -#[derive(Default)] -pub struct AvifImage { - pub primary_item: Mp4parseByteData, - pub alpha_item: Mp4parseByteData, - pub premultiplied_alpha: bool, -} - /// A unified interface for the parsers which have different contexts, but /// share the same pattern of construction. This allows unification of /// argument validation from C and minimizes the surface of unsafe code. @@ -451,11 +443,11 @@ trait ContextParser where Self: Sized, { - type Context; + type Context: Default; fn with_context(context: Self::Context) -> Self; - fn read(io: &mut T) -> mp4parse::Result; + fn read(io: &mut T, context: &mut Self::Context) -> mp4parse::Result<()>; } impl Mp4parseParser { @@ -478,11 +470,12 @@ impl ContextParser for Mp4parseParser { } } - fn read(io: &mut T) -> mp4parse::Result { - read_mp4(io) + fn read(io: &mut T, context: &mut Self::Context) -> mp4parse::Result<()> { + read_mp4(io, context) } } +#[derive(Default)] pub struct Mp4parseAvifParser { context: AvifContext, } @@ -500,8 +493,8 @@ impl ContextParser for Mp4parseAvifParser { Self { context } } - fn read(io: &mut T) -> mp4parse::Result { - read_avif(io) + fn read(io: &mut T, context: &mut Self::Context) -> mp4parse::Result<()> { + read_avif(io, context) } } @@ -604,8 +597,10 @@ unsafe fn mp4parse_new_common( fn mp4parse_new_common_safe( io: &mut T, ) -> Result<*mut P, Mp4parseStatus> { - P::read(io) - .map(P::with_context) + let mut context = P::Context::default(); + + P::read(io, &mut context) + .map(|_| P::with_context(context)) .and_then(|x| TryBox::try_new(x).map_err(mp4parse::Error::from)) .map(TryBox::into_raw) .map_err(Mp4parseStatus::from) @@ -1185,31 +1180,27 @@ fn mp4parse_get_track_video_info_safe( /// # Safety /// /// This function is unsafe because it dereferences both the parser and -/// avif_image raw pointers passed into it. Callers should ensure the parser -/// pointer points to a valid `Mp4parseAvifParser`, and that the avif_image -/// pointer points to a valid `AvifImage`. If there was not a previous +/// primary_item raw pointers passed into it. Callers should ensure the parser +/// pointer points to a valid `Mp4parseAvifParser`, and that the primary_item +/// pointer points to a valid `Mp4parseByteData`. If there was not a previous /// successful call to `mp4parse_avif_read()`, no guarantees are made as to -/// the state of `avif_image`. If `avif_image.alpha_item` is set to a -/// positive `length` and non-null `data`, then the `avif_image` contains an -/// valid alpha channel data. Otherwise, the image is opaque. +/// the state of `primary_item`. #[no_mangle] -pub unsafe extern "C" fn mp4parse_avif_get_image( +pub unsafe extern "C" fn mp4parse_avif_get_primary_item( parser: *mut Mp4parseAvifParser, - avif_image: *mut AvifImage, + primary_item: *mut Mp4parseByteData, ) -> Mp4parseStatus { - if parser.is_null() || avif_image.is_null() { + if parser.is_null() { return Mp4parseStatus::BadArg; } // Initialize fields to default values to ensure all fields are always valid. - *avif_image = Default::default(); + *primary_item = Default::default(); + let context = (*parser).context(); - (*avif_image).primary_item.set_data(context.primary_item()); - if let Some(context_alpha_item) = context.alpha_item() { - (*avif_image).alpha_item.set_data(context_alpha_item); - (*avif_image).premultiplied_alpha = context.premultiplied_alpha; - } + // TODO: check for a valid parsed context. See https://github.com/mozilla/mp4parse-rust/issues/195 + (*primary_item).set_data(&context.primary_item); Mp4parseStatus::Ok } diff --git a/toolkit/library/rust/shared/Cargo.toml b/toolkit/library/rust/shared/Cargo.toml index c840c509c96e..10fda1e6161a 100644 --- a/toolkit/library/rust/shared/Cargo.toml +++ b/toolkit/library/rust/shared/Cargo.toml @@ -9,7 +9,7 @@ description = "Shared Rust code for libxul" geckoservo = { path = "../../../../servo/ports/geckolib" } kvstore = { path = "../../../components/kvstore" } lmdb-rkv-sys = { version = "0.11", features = ["mdb_idl_logn_9"] } -mp4parse_capi = { git = "https://github.com/mozilla/mp4parse-rust", rev = "94fd2f16b1a569a35801c4e7d858c6e1b24020ff" } +mp4parse_capi = { git = "https://github.com/mozilla/mp4parse-rust", rev = "f7c35a30ff25521bebe64c19d3f306569ecb5385" } nserror = { path = "../../../../xpcom/rust/nserror" } nsstring = { path = "../../../../xpcom/rust/nsstring" } netwerk_helper = { path = "../../../../netwerk/base/rust-helper" }