new file mode 100644
--- /dev/null
+++ b/third_party/rust/cfg-if-0.1.1/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{".travis.yml":"50f67b20a376d437e0706d9bbb0343c677295529991370b2962f814c0b2efea3","Cargo.toml":"d217067290b088db7f696e02ecc25461a0277e5e5e3bca6c7c0412b604c3526b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"3fa9368c60bc701dea294fbacae0469188c4be1de79f82e972bb9b321776cd52","src/lib.rs":"74b287a91a46dc9d0c179053b439fd40c43ad5389fbd5199fff1cce0094726a6","tests/xcrate.rs":"30dcb70fbb9c96fda2b7825592558279f534776f72e2a8a0a3e26df4dedb3caa"},"package":"d0c47d456a36ebf0536a6705c83c1cbbcb9255fbc1d905a6ded104f479268a29"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cfg-if-0.1.1/.travis.yml
@@ -0,0 +1,23 @@
+language: rust
+rust:
+ - stable
+ - beta
+ - nightly
+sudo: false
+before_script:
+ - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
+script:
+ - cargo build --verbose
+ - cargo test --verbose
+ - rustdoc --test README.md -L target/debug -L target/debug/deps
+ - cargo doc --no-deps
+after_success:
+ - travis-cargo --only nightly doc-upload
+env:
+ global:
+ secure: "TyMGH+sbPmKs9lKCziKShxWr3G6im0owEchVrbUChWnQIQv1WydXftFoEoUsVl6qZspjehWK1b1AsnIgCXK0HtEi4DnqLsxs0s36bOjfg5yHBT/pETTr6kcq7KAL4Be4GmI331k6gT1Oi0TPFp7Sg9xpiWsQqKIHA5Szk2wpFQ8="
+
+
+notifications:
+ email:
+ on_success: never
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cfg-if-0.1.1/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "cfg-if"
+version = "0.1.1"
+authors = ["Alex Crichton <alex@alexcrichton.com>"]
+license = "MIT/Apache-2.0"
+readme = "README.md"
+repository = "https://github.com/alexcrichton/cfg-if"
+homepage = "https://github.com/alexcrichton/cfg-if"
+documentation = "http://alexcrichton.com/cfg-if"
+description = """
+A macro to ergonomically define an item depending on a large number of #[cfg]
+parameters. Structured like an if-else chain, the first matching branch is the
+item that gets emitted.
+"""
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cfg-if-0.1.1/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cfg-if-0.1.1/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2014 Alex Crichton
+
+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.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cfg-if-0.1.1/README.md
@@ -0,0 +1,44 @@
+# cfg-if
+
+[![Build Status](https://travis-ci.org/alexcrichton/cfg-if.svg?branch=master)](https://travis-ci.org/alexcrichton/cfg-if)
+
+[Documentation](http://alexcrichton.com/cfg-if)
+
+A macro to ergonomically define an item depending on a large number of #[cfg]
+parameters. Structured like an if-else chain, the first matching branch is the
+item that gets emitted.
+
+```toml
+[dependencies]
+cfg-if = "0.1"
+```
+
+## Example
+
+```rust
+#[macro_use]
+extern crate cfg_if;
+
+cfg_if! {
+ if #[cfg(unix)] {
+ fn foo() { /* unix specific functionality */ }
+ } else if #[cfg(target_pointer_width = "32")] {
+ fn foo() { /* non-unix, 32-bit functionality */ }
+ } else {
+ fn foo() { /* fallback implementation */ }
+ }
+}
+
+fn main() {
+ foo();
+}
+```
+
+# License
+
+`cfg-if` is primarily distributed under the terms of both the MIT license and
+the Apache License (Version 2.0), with portions covered by various BSD-like
+licenses.
+
+See LICENSE-APACHE, and LICENSE-MIT for details.
+
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cfg-if-0.1.1/src/lib.rs
@@ -0,0 +1,103 @@
+//! A macro for defining #[cfg] if-else statements.
+//!
+//! The macro provided by this crate, `cfg_if`, is similar to the `if/elif` C
+//! preprocessor macro by allowing definition of a cascade of `#[cfg]` cases,
+//! emitting the implementation which matches first.
+//!
+//! This allows you to conveniently provide a long list #[cfg]'d blocks of code
+//! without having to rewrite each clause multiple times.
+//!
+//! # Example
+//!
+//! ```
+//! #[macro_use]
+//! extern crate cfg_if;
+//!
+//! cfg_if! {
+//! if #[cfg(unix)] {
+//! fn foo() { /* unix specific functionality */ }
+//! } else if #[cfg(target_pointer_width = "32")] {
+//! fn foo() { /* non-unix, 32-bit functionality */ }
+//! } else {
+//! fn foo() { /* fallback implementation */ }
+//! }
+//! }
+//!
+//! # fn main() {}
+//! ```
+
+#![no_std]
+
+#![doc(html_root_url = "http://alexcrichton.com/cfg-if")]
+#![deny(missing_docs)]
+#![cfg_attr(test, deny(warnings))]
+
+#[macro_export]
+macro_rules! cfg_if {
+ ($(
+ if #[cfg($($meta:meta),*)] { $($it:item)* }
+ ) else * else {
+ $($it2:item)*
+ }) => {
+ __cfg_if_items! {
+ () ;
+ $( ( ($($meta),*) ($($it)*) ), )*
+ ( () ($($it2)*) ),
+ }
+ }
+}
+
+#[macro_export]
+#[doc(hidden)]
+macro_rules! __cfg_if_items {
+ (($($not:meta,)*) ; ) => {};
+ (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
+ __cfg_if_apply! { cfg(all($($m,)* not(any($($not),*)))), $($it)* }
+ __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* }
+ }
+}
+
+#[macro_export]
+#[doc(hidden)]
+macro_rules! __cfg_if_apply {
+ ($m:meta, $($it:item)*) => {
+ $(#[$m] $it)*
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ cfg_if! {
+ if #[cfg(test)] {
+ use core::option::Option as Option2;
+ fn works1() -> Option2<u32> { Some(1) }
+ } else {
+ fn works1() -> Option<u32> { None }
+ }
+ }
+
+ cfg_if! {
+ if #[cfg(foo)] {
+ fn works2() -> bool { false }
+ } else if #[cfg(test)] {
+ fn works2() -> bool { true }
+ } else {
+ fn works2() -> bool { false }
+ }
+ }
+
+ cfg_if! {
+ if #[cfg(foo)] {
+ fn works3() -> bool { false }
+ } else {
+ fn works3() -> bool { true }
+ }
+ }
+
+ #[test]
+ fn it_works() {
+ assert!(works1().is_some());
+ assert!(works2());
+ assert!(works3());
+ }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cfg-if-0.1.1/tests/xcrate.rs
@@ -0,0 +1,17 @@
+#[macro_use]
+extern crate cfg_if;
+
+cfg_if! {
+ if #[cfg(foo)] {
+ fn works() -> bool { false }
+ } else if #[cfg(test)] {
+ fn works() -> bool { true }
+ } else {
+ fn works() -> bool { false }
+ }
+}
+
+#[test]
+fn smoke() {
+ assert!(works());
+}
--- a/third_party/rust/cfg-if/.cargo-checksum.json
+++ b/third_party/rust/cfg-if/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".travis.yml":"50f67b20a376d437e0706d9bbb0343c677295529991370b2962f814c0b2efea3","Cargo.toml":"d217067290b088db7f696e02ecc25461a0277e5e5e3bca6c7c0412b604c3526b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"3fa9368c60bc701dea294fbacae0469188c4be1de79f82e972bb9b321776cd52","src/lib.rs":"74b287a91a46dc9d0c179053b439fd40c43ad5389fbd5199fff1cce0094726a6","tests/xcrate.rs":"30dcb70fbb9c96fda2b7825592558279f534776f72e2a8a0a3e26df4dedb3caa"},"package":"d0c47d456a36ebf0536a6705c83c1cbbcb9255fbc1d905a6ded104f479268a29"}
\ No newline at end of file
+{"files":{".travis.yml":"50f67b20a376d437e0706d9bbb0343c677295529991370b2962f814c0b2efea3","Cargo.toml":"764b9ce160653e841430da3919ff968b957ff811f7da42c8483c8bfc2f06be25","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"3fa9368c60bc701dea294fbacae0469188c4be1de79f82e972bb9b321776cd52","src/lib.rs":"6915169e3ca05f28e1cb0e052379d74f2496400de1240b74c56e55c2674a6560","tests/xcrate.rs":"30dcb70fbb9c96fda2b7825592558279f534776f72e2a8a0a3e26df4dedb3caa"},"package":"d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"}
\ No newline at end of file
--- a/third_party/rust/cfg-if/Cargo.toml
+++ b/third_party/rust/cfg-if/Cargo.toml
@@ -1,11 +1,11 @@
[package]
name = "cfg-if"
-version = "0.1.1"
+version = "0.1.2"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
license = "MIT/Apache-2.0"
readme = "README.md"
repository = "https://github.com/alexcrichton/cfg-if"
homepage = "https://github.com/alexcrichton/cfg-if"
documentation = "http://alexcrichton.com/cfg-if"
description = """
A macro to ergonomically define an item depending on a large number of #[cfg]
--- a/third_party/rust/cfg-if/src/lib.rs
+++ b/third_party/rust/cfg-if/src/lib.rs
@@ -39,16 +39,29 @@ macro_rules! cfg_if {
) else * else {
$($it2:item)*
}) => {
__cfg_if_items! {
() ;
$( ( ($($meta),*) ($($it)*) ), )*
( () ($($it2)*) ),
}
+ };
+ (
+ if #[cfg($($i_met:meta),*)] { $($i_it:item)* }
+ $(
+ else if #[cfg($($e_met:meta),*)] { $($e_it:item)* }
+ )*
+ ) => {
+ __cfg_if_items! {
+ () ;
+ ( ($($i_met),*) ($($i_it)*) ),
+ $( ( ($($e_met),*) ($($e_it)*) ), )*
+ ( () () ),
+ }
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! __cfg_if_items {
(($($not:meta,)*) ; ) => {};
(($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
@@ -89,15 +102,32 @@ mod tests {
cfg_if! {
if #[cfg(foo)] {
fn works3() -> bool { false }
} else {
fn works3() -> bool { true }
}
}
+ cfg_if! {
+ if #[cfg(test)] {
+ use core::option::Option as Option3;
+ fn works4() -> Option3<u32> { Some(1) }
+ }
+ }
+
+ cfg_if! {
+ if #[cfg(foo)] {
+ fn works5() -> bool { false }
+ } else if #[cfg(test)] {
+ fn works5() -> bool { true }
+ }
+ }
+
#[test]
fn it_works() {
assert!(works1().is_some());
assert!(works2());
assert!(works3());
+ assert!(works4().is_some());
+ assert!(works5());
}
}
--- a/third_party/rust/core-text/.cargo-checksum.json
+++ b/third_party/rust/core-text/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".travis.yml":"6aad961651169d31d79c0595624d1777b5c4cbb4cf2bed9a126c7e72d29411fd","COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"7b694b4c2584d66e353968c93b4d639b7cbee87595b7323d721338299c2f80ec","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"0c82015d302c9937e6376debd961350afeaeb6dde228aac95e3a3115c5813613","src/font.rs":"de24c0023079289752a2fdb435012ba77982c108695d931926e6b629f0a7863a","src/font_collection.rs":"640402b679756d4cbf868d2cb96bb8c77f363ee36c42f7584d831a923c9006a2","src/font_descriptor.rs":"71781af6b428278bd1ed2a13e3aafa4be8f263e835c879016e697c5bc4104de8","src/font_manager.rs":"de5e22620528322d6811d01f03975c53b676ec743297590de5e17a45393df0f1","src/lib.rs":"dfff85c1e4dbbc5d360dd022a8e539be4e5f195d8695467e1dcb25bd0bac4f47"},"package":"2c737a5c1f112943c961ed270aea64f7d0b01b425d327b040fa32b155646e07f"}
\ No newline at end of file
+{"files":{".travis.yml":"6aad961651169d31d79c0595624d1777b5c4cbb4cf2bed9a126c7e72d29411fd","COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"7a7725d84ea421fd0b48ddaa17e6abe58e3dd1507232dc03a76e2fbcb305ebd2","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"0c82015d302c9937e6376debd961350afeaeb6dde228aac95e3a3115c5813613","src/font.rs":"640f17efb3492ad0e9c318a4e2e23da87120f817d055475290e2f58f0212577d","src/font_collection.rs":"4fbe6a45d227771e148498bab5f915bd6e7cb6f060427b8f4ac626a44fcee288","src/font_descriptor.rs":"188dfad16e1081ec411dbdce1d8210be187a2dac0cf983444f01d5122e7d8e6e","src/font_manager.rs":"de5e22620528322d6811d01f03975c53b676ec743297590de5e17a45393df0f1","src/lib.rs":"bd072cf53ebb643e4d21379d4487e60745999d20eab9caee8e56daa430cb65ca"},"package":"2bd581c37283d0c23311d179aefbb891f2324ee0405da58a26e8594ab76e5748"}
\ No newline at end of file
--- a/third_party/rust/core-text/Cargo.toml
+++ b/third_party/rust/core-text/Cargo.toml
@@ -7,17 +7,17 @@
#
# 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 = "core-text"
-version = "9.0.0"
+version = "9.2.0"
authors = ["The Servo Project Developers"]
description = "Bindings to the Core Text framework."
license = "MIT/Apache-2.0"
repository = "https://github.com/servo/core-text-rs"
[dependencies.core-foundation]
version = "0.5"
[dependencies.core-graphics]
--- a/third_party/rust/core-text/src/font.rs
+++ b/third_party/rust/core-text/src/font.rs
@@ -4,34 +4,34 @@
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(non_upper_case_globals)]
+use font_descriptor;
use font_descriptor::{CTFontDescriptor, CTFontDescriptorRef, CTFontOrientation};
use font_descriptor::{CTFontSymbolicTraits, CTFontTraits, SymbolicTraitAccessors, TraitAccessors};
use core_foundation::array::{CFArray, CFArrayRef};
-use core_foundation::base::{CFIndex, CFOptionFlags, CFTypeID, CFRelease, CFRetain, CFTypeRef, TCFType};
+use core_foundation::base::{CFIndex, CFOptionFlags, CFTypeID, CFTypeRef, TCFType};
use core_foundation::data::{CFData, CFDataRef};
-use core_foundation::dictionary::CFDictionaryRef;
+use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
use core_foundation::string::{CFString, CFStringRef, UniChar};
use core_foundation::url::{CFURL, CFURLRef};
use core_graphics::base::CGFloat;
use core_graphics::context::CGContext;
use core_graphics::font::{CGGlyph, CGFont};
use core_graphics::geometry::{CGAffineTransform, CGPoint, CGRect, CGSize};
use core_graphics::path::CGPath;
use foreign_types::ForeignType;
use libc::{self, size_t, c_void};
-use std::mem;
use std::ptr;
type CGContextRef = *mut <CGContext as ForeignType>::CType;
type CGFontRef = *mut <CGFont as ForeignType>::CType;
type CGPathRef = *mut <CGPath as ForeignType>::CType;
pub type CTFontUIFontType = u32;
// kCTFontNoFontType: CTFontUIFontType = -1;
@@ -75,132 +75,94 @@ pub const kCTFontOptionsDefault: CTFontO
pub const kCTFontOptionsPreventAutoActivation: CTFontOptions = (1 << 0);
pub const kCTFontOptionsPreferSystemFont: CTFontOptions = (1 << 2);
#[repr(C)]
pub struct __CTFont(c_void);
pub type CTFontRef = *const __CTFont;
-#[derive(Debug)]
-pub struct CTFont {
- obj: CTFontRef,
-}
-
-impl Drop for CTFont {
- fn drop(&mut self) {
- unsafe {
- CFRelease(self.as_CFTypeRef())
- }
- }
-}
-
-impl Clone for CTFont {
- #[inline]
- fn clone(&self) -> CTFont {
- unsafe {
- TCFType::wrap_under_get_rule(self.obj)
- }
- }
+declare_TCFType! {
+ CTFont, CTFontRef
}
-
-impl TCFType for CTFont {
- type Ref = CTFontRef;
-
- #[inline]
- fn as_concrete_TypeRef(&self) -> CTFontRef {
- self.obj
- }
-
- #[inline]
- unsafe fn wrap_under_get_rule(reference: CTFontRef) -> CTFont {
- let reference: CTFontRef = mem::transmute(CFRetain(mem::transmute(reference)));
- TCFType::wrap_under_create_rule(reference)
- }
-
- #[inline]
- unsafe fn wrap_under_create_rule(obj: CTFontRef) -> CTFont {
- CTFont {
- obj: obj,
- }
- }
-
- #[inline]
- fn as_CFTypeRef(&self) -> CFTypeRef {
- unsafe {
- mem::transmute(self.as_concrete_TypeRef())
- }
- }
-
- #[inline]
- fn type_id() -> CFTypeID {
- unsafe {
- CTFontGetTypeID()
- }
- }
-}
+impl_TCFType!(CTFont, CTFontRef, CTFontGetTypeID);
+impl_CFTypeDescription!(CTFont);
pub fn new_from_CGFont(cgfont: &CGFont, pt_size: f64) -> CTFont {
unsafe {
let font_ref = CTFontCreateWithGraphicsFont(cgfont.as_ptr() as *mut _,
pt_size as CGFloat,
ptr::null(),
ptr::null());
- TCFType::wrap_under_create_rule(font_ref)
+ CTFont::wrap_under_create_rule(font_ref)
+ }
+}
+
+pub fn new_from_CGFont_with_variations(cgfont: &CGFont,
+ pt_size: f64,
+ variations: &CFDictionary)
+ -> CTFont {
+ unsafe {
+ let font_desc = font_descriptor::new_from_variations(variations);
+ let font_ref = CTFontCreateWithGraphicsFont(cgfont.as_ptr() as *mut _,
+ pt_size as CGFloat,
+ ptr::null(),
+ font_desc.as_concrete_TypeRef());
+ CTFont::wrap_under_create_rule(font_ref)
}
}
pub fn new_from_descriptor(desc: &CTFontDescriptor, pt_size: f64) -> CTFont {
unsafe {
let font_ref = CTFontCreateWithFontDescriptor(desc.as_concrete_TypeRef(),
pt_size as CGFloat,
ptr::null());
- TCFType::wrap_under_create_rule(font_ref)
+ CTFont::wrap_under_create_rule(font_ref)
}
}
pub fn new_from_name(name: &str, pt_size: f64) -> Result<CTFont, ()> {
unsafe {
let name: CFString = name.parse().unwrap();
let font_ref = CTFontCreateWithName(name.as_concrete_TypeRef(),
pt_size as CGFloat,
ptr::null());
if font_ref.is_null() {
Err(())
} else {
- Ok(TCFType::wrap_under_create_rule(font_ref))
+ Ok(CTFont::wrap_under_create_rule(font_ref))
}
}
}
impl CTFont {
// Properties
pub fn symbolic_traits(&self) -> CTFontSymbolicTraits {
unsafe {
- CTFontGetSymbolicTraits(self.obj)
+ CTFontGetSymbolicTraits(self.0)
}
}
}
impl CTFont {
// Creation methods
pub fn copy_to_CGFont(&self) -> CGFont {
unsafe {
- let cgfont_ref = CTFontCopyGraphicsFont(self.obj, ptr::null_mut());
+ let cgfont_ref = CTFontCopyGraphicsFont(self.0, ptr::null_mut());
CGFont::from_ptr(cgfont_ref as *mut _)
}
}
pub fn clone_with_font_size(&self, size: f64) -> CTFont {
unsafe {
- let font_ref = CTFontCreateCopyWithAttributes(self.obj,
+ let font_ref = CTFontCreateCopyWithAttributes(self.0,
size as CGFloat,
ptr::null(),
ptr::null());
- TCFType::wrap_under_create_rule(font_ref)
+ CTFont::wrap_under_create_rule(font_ref)
}
}
// Names
pub fn family_name(&self) -> String {
unsafe {
let value = get_string_by_name_key(self, kCTFontFamilyNameKey);
value.expect("Fonts should always have a family name.")
@@ -225,102 +187,102 @@ impl CTFont {
unsafe {
let value = get_string_by_name_key(self, kCTFontPostScriptNameKey);
value.expect("Fonts should always have a PostScript name.")
}
}
pub fn all_traits(&self) -> CTFontTraits {
unsafe {
- TCFType::wrap_under_create_rule(CTFontCopyTraits(self.obj))
+ CTFontTraits::wrap_under_create_rule(CTFontCopyTraits(self.0))
}
}
// Font metrics
pub fn ascent(&self) -> CGFloat {
unsafe {
- CTFontGetAscent(self.obj)
+ CTFontGetAscent(self.0)
}
}
pub fn descent(&self) -> CGFloat {
unsafe {
- CTFontGetDescent(self.obj)
+ CTFontGetDescent(self.0)
}
}
pub fn underline_thickness(&self) -> CGFloat {
unsafe {
- CTFontGetUnderlineThickness(self.obj)
+ CTFontGetUnderlineThickness(self.0)
}
}
pub fn underline_position(&self) -> CGFloat {
unsafe {
- CTFontGetUnderlinePosition(self.obj)
+ CTFontGetUnderlinePosition(self.0)
}
}
pub fn bounding_box(&self) -> CGRect {
unsafe {
- CTFontGetBoundingBox(self.obj)
+ CTFontGetBoundingBox(self.0)
}
}
pub fn leading(&self) -> CGFloat {
unsafe {
- CTFontGetLeading(self.obj)
+ CTFontGetLeading(self.0)
}
}
pub fn units_per_em(&self) -> libc::c_uint {
unsafe {
- CTFontGetUnitsPerEm(self.obj)
+ CTFontGetUnitsPerEm(self.0)
}
}
pub fn x_height(&self) -> CGFloat {
unsafe {
- CTFontGetXHeight(self.obj)
+ CTFontGetXHeight(self.0)
}
}
pub fn pt_size(&self) -> CGFloat {
unsafe {
- CTFontGetSize(self.obj)
+ CTFontGetSize(self.0)
}
}
pub fn get_glyphs_for_characters(&self, characters: *const UniChar, glyphs: *mut CGGlyph, count: CFIndex)
-> bool {
unsafe {
- CTFontGetGlyphsForCharacters(self.obj, characters, glyphs, count)
+ CTFontGetGlyphsForCharacters(self.0, characters, glyphs, count)
}
}
pub fn get_advances_for_glyphs(&self,
orientation: CTFontOrientation,
glyphs: *const CGGlyph,
advances: *mut CGSize,
count: CFIndex)
-> f64 {
unsafe {
- CTFontGetAdvancesForGlyphs(self.obj, orientation, glyphs, advances, count) as f64
+ CTFontGetAdvancesForGlyphs(self.0, orientation, glyphs, advances, count) as f64
}
}
pub fn get_font_table(&self, tag: u32) -> Option<CFData> {
unsafe {
- let result = CTFontCopyTable(self.obj,
+ let result = CTFontCopyTable(self.0,
tag as CTFontTableTag,
kCTFontTableOptionsExcludeSynthetic);
if result.is_null() {
None
} else {
- Some(TCFType::wrap_under_create_rule(result))
+ Some(CFData::wrap_under_create_rule(result))
}
}
}
pub fn get_bounding_rects_for_glyphs(&self, orientation: CTFontOrientation, glyphs: &[CGGlyph])
-> CGRect {
unsafe {
let result = CTFontGetBoundingRectsForGlyphs(self.as_concrete_TypeRef(),
@@ -340,47 +302,46 @@ impl CTFont {
positions.as_ptr(),
glyphs.len() as size_t,
context.as_ptr())
}
}
pub fn url(&self) -> Option<CFURL> {
unsafe {
- let result = CTFontCopyAttribute(self.obj, kCTFontURLAttribute);
+ let result = CTFontCopyAttribute(self.0, kCTFontURLAttribute);
if result.is_null() {
None
} else {
- Some(TCFType::wrap_under_create_rule(result as CFURLRef))
+ Some(CFURL::wrap_under_create_rule(result as CFURLRef))
}
}
}
pub fn create_path_for_glyph(&self, glyph: CGGlyph, matrix: &CGAffineTransform)
-> Result<CGPath, ()> {
unsafe {
- let path = CTFontCreatePathForGlyph(self.obj, glyph, matrix);
+ let path = CTFontCreatePathForGlyph(self.0, glyph, matrix);
if path.is_null() {
Err(())
} else {
Ok(CGPath::from_ptr(path))
}
}
}
}
// Helper methods
fn get_string_by_name_key(font: &CTFont, name_key: CFStringRef) -> Option<String> {
unsafe {
let result = CTFontCopyName(font.as_concrete_TypeRef(), name_key);
if result.is_null() {
None
} else {
- let string: CFString = TCFType::wrap_under_create_rule(result);
- Some(string.to_string())
+ Some(CFString::wrap_under_create_rule(result).to_string())
}
}
}
pub fn debug_font_names(font: &CTFont) {
fn get_key(font: &CTFont, key: CFStringRef) -> String {
get_string_by_name_key(font, key).unwrap()
}
@@ -410,17 +371,17 @@ pub fn debug_font_traits(font: &CTFont)
}
#[cfg(feature = "mountainlion")]
pub fn cascade_list_for_languages(font: &CTFont, language_pref_list: &CFArray<CFString>) -> CFArray<CTFontDescriptor> {
unsafe {
let font_collection_ref =
CTFontCopyDefaultCascadeListForLanguages(font.as_concrete_TypeRef(),
language_pref_list.as_concrete_TypeRef());
- TCFType::wrap_under_create_rule(font_collection_ref)
+ CFArray::wrap_under_create_rule(font_collection_ref)
}
}
#[link(name = "CoreText", kind = "framework")]
extern {
/*
* CTFont.h
*/
@@ -467,17 +428,17 @@ extern {
/* Creating Fonts */
fn CTFontCreateWithName(name: CFStringRef, size: CGFloat, matrix: *const CGAffineTransform) -> CTFontRef;
//fn CTFontCreateWithNameAndOptions
fn CTFontCreateWithFontDescriptor(descriptor: CTFontDescriptorRef, size: CGFloat,
matrix: *const CGAffineTransform) -> CTFontRef;
//fn CTFontCreateWithFontDescriptorAndOptions
//fn CTFontCreateUIFontForLanguage
- fn CTFontCreateCopyWithAttributes(font: CTFontRef, size: CGFloat, matrix: *const CGAffineTransform,
+ fn CTFontCreateCopyWithAttributes(font: CTFontRef, size: CGFloat, matrix: *const CGAffineTransform,
attributes: CTFontDescriptorRef) -> CTFontRef;
//fn CTFontCreateCopyWithSymbolicTraits
//fn CTFontCreateCopyWithFamily
//fn CTFontCreateForString
/* Getting Font Data */
//fn CTFontCopyFontDescriptor(font: CTFontRef) -> CTFontDescriptorRef;
fn CTFontCopyAttribute(font: CTFontRef, attribute: CFStringRef) -> CFTypeRef;
@@ -487,17 +448,17 @@ extern {
fn CTFontCopyTraits(font: CTFontRef) -> CFDictionaryRef;
/* Getting Font Names */
//fn CTFontCopyPostScriptName(font: CTFontRef) -> CFStringRef;
//fn CTFontCopyFamilyName(font: CTFontRef) -> CFStringRef;
//fn CTFontCopyFullName(font: CTFontRef) -> CFStringRef;
//fn CTFontCopyDisplayName(font: CTFontRef) -> CFStringRef;
fn CTFontCopyName(font: CTFontRef, nameKey: CFStringRef) -> CFStringRef;
- //fn CTFontCopyLocalizedName(font: CTFontRef, nameKey: CFStringRef,
+ //fn CTFontCopyLocalizedName(font: CTFontRef, nameKey: CFStringRef,
// language: *CFStringRef) -> CFStringRef;
#[cfg(feature = "mountainlion")]
fn CTFontCopyDefaultCascadeListForLanguages(font: CTFontRef, languagePrefList: CFArrayRef) -> CFArrayRef;
/* Working With Encoding */
//fn CTFontCopyCharacterSet
//fn CTFontGetStringEncoding
@@ -544,18 +505,18 @@ extern {
positions: *const CGPoint,
count: size_t,
context: CGContextRef);
//fn CTFontGetLigatureCaretPositions
/* Converting Fonts */
fn CTFontCopyGraphicsFont(font: CTFontRef, attributes: *mut CTFontDescriptorRef)
-> CGFontRef;
- fn CTFontCreateWithGraphicsFont(graphicsFont: CGFontRef, size: CGFloat,
- matrix: *const CGAffineTransform,
+ fn CTFontCreateWithGraphicsFont(graphicsFont: CGFontRef, size: CGFloat,
+ matrix: *const CGAffineTransform,
attributes: CTFontDescriptorRef) -> CTFontRef;
//fn CTFontGetPlatformFont
//fn CTFontCreateWithPlatformFont
//fn CTFontCreateWithQuickdrawInstance
/* Getting Font Table Data */
//fn CTFontCopyAvailableTables(font: CTFontRef, options: CTFontTableOptions) -> CFArrayRef;
fn CTFontCopyTable(font: CTFontRef, table: CTFontTableTag, options: CTFontTableOptions) -> CFDataRef;
--- a/third_party/rust/core-text/src/font_collection.rs
+++ b/third_party/rust/core-text/src/font_collection.rs
@@ -7,157 +7,114 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use font_descriptor;
use font_descriptor::{CTFontDescriptor, CTFontDescriptorCreateMatchingFontDescriptors};
use font_manager::CTFontManagerCopyAvailableFontFamilyNames;
use core_foundation::array::{CFArray, CFArrayRef};
-use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};
+use core_foundation::base::{CFTypeID, TCFType};
use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
use core_foundation::number::CFNumber;
use core_foundation::set::CFSet;
use core_foundation::string::{CFString, CFStringRef};
use libc::c_void;
-use std::mem;
use std::ptr;
#[repr(C)]
pub struct __CTFontCollection(c_void);
pub type CTFontCollectionRef = *const __CTFontCollection;
-#[derive(Debug)]
-pub struct CTFontCollection {
- obj: CTFontCollectionRef,
+declare_TCFType! {
+ CTFontCollection, CTFontCollectionRef
}
-
-impl Drop for CTFontCollection {
- fn drop(&mut self) {
- unsafe {
- CFRelease(self.as_CFTypeRef())
- }
- }
-}
-
-impl TCFType for CTFontCollection {
- type Ref = CTFontCollectionRef;
-
- #[inline]
- fn as_concrete_TypeRef(&self) -> CTFontCollectionRef {
- self.obj
- }
+impl_TCFType!(CTFontCollection, CTFontCollectionRef, CTFontCollectionGetTypeID);
+impl_CFTypeDescription!(CTFontCollection);
- #[inline]
- unsafe fn wrap_under_get_rule(reference: CTFontCollectionRef) -> CTFontCollection {
- let reference: CTFontCollectionRef = mem::transmute(CFRetain(mem::transmute(reference)));
- TCFType::wrap_under_create_rule(reference)
- }
-
- #[inline]
- unsafe fn wrap_under_create_rule(obj: CTFontCollectionRef) -> CTFontCollection {
- CTFontCollection {
- obj: obj,
- }
- }
-
- #[inline]
- fn as_CFTypeRef(&self) -> CFTypeRef {
- unsafe {
- mem::transmute(self.as_concrete_TypeRef())
- }
- }
-
- #[inline]
- fn type_id() -> CFTypeID {
- unsafe {
- CTFontCollectionGetTypeID()
- }
- }
-}
impl CTFontCollection {
pub fn get_descriptors(&self) -> CFArray<CTFontDescriptor> {
// surprise! this function follows the Get rule, despite being named *Create*.
// So we have to addRef it to avoid CTFontCollection from double freeing it later.
unsafe {
- TCFType::wrap_under_get_rule(CTFontCollectionCreateMatchingFontDescriptors(self.obj))
+ CFArray::wrap_under_get_rule(CTFontCollectionCreateMatchingFontDescriptors(self.0))
}
}
}
pub fn new_from_descriptors(descs: &CFArray<CTFontDescriptor>) -> CTFontCollection {
unsafe {
- let key: CFString = TCFType::wrap_under_get_rule(kCTFontCollectionRemoveDuplicatesOption);
+ let key = CFString::wrap_under_get_rule(kCTFontCollectionRemoveDuplicatesOption);
let value = CFNumber::from(1i64);
let options = CFDictionary::from_CFType_pairs(&[ (key.as_CFType(), value.as_CFType()) ]);
let font_collection_ref =
CTFontCollectionCreateWithFontDescriptors(descs.as_concrete_TypeRef(),
options.as_concrete_TypeRef());
- TCFType::wrap_under_create_rule(font_collection_ref)
+ CTFontCollection::wrap_under_create_rule(font_collection_ref)
}
}
pub fn create_for_all_families() -> CTFontCollection {
unsafe {
- let key: CFString = TCFType::wrap_under_get_rule(kCTFontCollectionRemoveDuplicatesOption);
+ let key = CFString::wrap_under_get_rule(kCTFontCollectionRemoveDuplicatesOption);
let value = CFNumber::from(1i64);
let options = CFDictionary::from_CFType_pairs(&[ (key.as_CFType(), value.as_CFType()) ]);
let font_collection_ref =
CTFontCollectionCreateFromAvailableFonts(options.as_concrete_TypeRef());
- TCFType::wrap_under_create_rule(font_collection_ref)
+ CTFontCollection::wrap_under_create_rule(font_collection_ref)
}
}
pub fn create_for_family(family: &str) -> Option<CTFontCollection> {
use font_descriptor::kCTFontFamilyNameAttribute;
unsafe {
- let family_attr: CFString = TCFType::wrap_under_get_rule(kCTFontFamilyNameAttribute);
+ let family_attr = CFString::wrap_under_get_rule(kCTFontFamilyNameAttribute);
let family_name: CFString = family.parse().unwrap();
let specified_attrs = CFDictionary::from_CFType_pairs(&[
(family_attr.as_CFType(), family_name.as_CFType())
]);
let wildcard_desc: CTFontDescriptor =
font_descriptor::new_from_attributes(&specified_attrs);
let mandatory_attrs = CFSet::from_slice(&[ family_attr.as_CFType() ]);
let matched_descs = CTFontDescriptorCreateMatchingFontDescriptors(
wildcard_desc.as_concrete_TypeRef(),
mandatory_attrs.as_concrete_TypeRef());
if matched_descs == ptr::null() {
return None;
}
- let matched_descs: CFArray<CTFontDescriptor> = TCFType::wrap_under_create_rule(matched_descs);
+ let matched_descs = CFArray::wrap_under_create_rule(matched_descs);
// I suppose one doesn't even need the CTFontCollection object at this point.
// But we stick descriptors into and out of it just to provide a nice wrapper API.
Some(new_from_descriptors(&matched_descs))
}
}
pub fn get_family_names() -> CFArray<CFString> {
unsafe {
- TCFType::wrap_under_create_rule(CTFontManagerCopyAvailableFontFamilyNames())
+ CFArray::wrap_under_create_rule(CTFontManagerCopyAvailableFontFamilyNames())
}
}
extern {
/*
* CTFontCollection.h
*/
static kCTFontCollectionRemoveDuplicatesOption: CFStringRef;
//fn CTFontCollectionCreateCopyWithFontDescriptors(original: CTFontCollectionRef,
// descriptors: CFArrayRef,
// options: CFDictionaryRef) -> CTFontCollectionRef;
fn CTFontCollectionCreateFromAvailableFonts(options: CFDictionaryRef) -> CTFontCollectionRef;
- // this stupid function doesn't actually do any wildcard expansion;
+ // this stupid function doesn't actually do any wildcard expansion;
// it just chooses the best match. Use
// CTFontDescriptorCreateMatchingDescriptors instead.
fn CTFontCollectionCreateMatchingFontDescriptors(collection: CTFontCollectionRef) -> CFArrayRef;
fn CTFontCollectionCreateWithFontDescriptors(descriptors: CFArrayRef,
options: CFDictionaryRef) -> CTFontCollectionRef;
//fn CTFontCollectionCreateMatchingFontDescriptorsSortedWithCallback;
fn CTFontCollectionGetTypeID() -> CFTypeID;
}
--- a/third_party/rust/core-text/src/font_descriptor.rs
+++ b/third_party/rust/core-text/src/font_descriptor.rs
@@ -5,22 +5,22 @@
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(non_upper_case_globals)]
use core_foundation::array::CFArrayRef;
-use core_foundation::base::{CFRelease, CFRetain, CFType, CFTypeID, CFTypeRef, TCFType};
+use core_foundation::base::{CFType, CFTypeID, CFTypeRef, TCFType};
use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
use core_foundation::number::{CFNumber, CFNumberRef};
use core_foundation::set::CFSetRef;
use core_foundation::string::{CFString, CFStringRef};
-use core_foundation::url::CFURL;
+use core_foundation::url::{CFURLCopyFileSystemPath, kCFURLPOSIXPathStyle, CFURL};
use core_graphics::base::CGFloat;
use libc::c_void;
use std::mem;
/*
* CTFontTraits.h
*/
@@ -126,17 +126,17 @@ pub trait TraitAccessors {
trait TraitAccessorPrivate {
unsafe fn extract_number_for_key(&self, key: CFStringRef) -> CFNumber;
}
impl TraitAccessorPrivate for CTFontTraits {
unsafe fn extract_number_for_key(&self, key: CFStringRef) -> CFNumber {
let cftype = self.get_CFType(mem::transmute(key));
assert!(cftype.instance_of::<CFNumber>());
- TCFType::wrap_under_get_rule(mem::transmute(cftype.as_CFTypeRef()))
+ CFNumber::wrap_under_get_rule(mem::transmute(cftype.as_CFTypeRef()))
}
}
impl TraitAccessors for CTFontTraits {
fn symbolic_traits(&self) -> CTFontSymbolicTraits {
unsafe {
let number = self.extract_number_for_key(kCTFontSymbolicTrait);
@@ -182,76 +182,34 @@ pub const kCTFontPriorityUser: CTFontPri
pub const kCTFontPriorityDynamic: CTFontPriority = 50000;
pub const kCTFontPriorityProcess: CTFontPriority = 60000;
#[repr(C)]
pub struct __CTFontDescriptor(c_void);
pub type CTFontDescriptorRef = *const __CTFontDescriptor;
-#[derive(Debug)]
-pub struct CTFontDescriptor {
- obj: CTFontDescriptorRef,
+declare_TCFType! {
+ CTFontDescriptor, CTFontDescriptorRef
}
-
-impl Drop for CTFontDescriptor {
- fn drop(&mut self) {
- unsafe {
- CFRelease(self.as_CFTypeRef())
- }
- }
-}
-
-impl TCFType for CTFontDescriptor {
- type Ref = CTFontDescriptorRef;
-
- #[inline]
- fn as_concrete_TypeRef(&self) -> CTFontDescriptorRef {
- self.obj
- }
+impl_TCFType!(CTFontDescriptor, CTFontDescriptorRef, CTFontDescriptorGetTypeID);
+impl_CFTypeDescription!(CTFontDescriptor);
- #[inline]
- unsafe fn wrap_under_get_rule(reference: CTFontDescriptorRef) -> CTFontDescriptor {
- let reference: CTFontDescriptorRef = mem::transmute(CFRetain(mem::transmute(reference)));
- TCFType::wrap_under_create_rule(reference)
- }
-
- #[inline]
- fn as_CFTypeRef(&self) -> CFTypeRef {
- unsafe {
- mem::transmute(self.as_concrete_TypeRef())
- }
- }
-
- #[inline]
- unsafe fn wrap_under_create_rule(obj: CTFontDescriptorRef) -> CTFontDescriptor {
- CTFontDescriptor {
- obj: obj,
- }
- }
-
- #[inline]
- fn type_id() -> CFTypeID {
- unsafe {
- CTFontDescriptorGetTypeID()
- }
- }
-}
impl CTFontDescriptor {
fn get_string_attribute(&self, attribute: CFStringRef) -> Option<String> {
unsafe {
- let value = CTFontDescriptorCopyAttribute(self.obj, attribute);
+ let value = CTFontDescriptorCopyAttribute(self.0, attribute);
if value.is_null() {
return None
}
- let value: CFType = TCFType::wrap_under_get_rule(value);
+ let value = CFType::wrap_under_create_rule(value);
assert!(value.instance_of::<CFString>());
- let s: CFString = TCFType::wrap_under_get_rule(mem::transmute(value.as_CFTypeRef()));
+ let s = CFString::wrap_under_get_rule(mem::transmute(value.as_CFTypeRef()));
Some(s.to_string())
}
}
}
impl CTFontDescriptor {
pub fn family_name(&self) -> String {
@@ -279,34 +237,57 @@ impl CTFontDescriptor {
unsafe {
let value = self.get_string_attribute(kCTFontDisplayNameAttribute);
value.expect("A font must have a non-null display name.")
}
}
pub fn font_path(&self) -> Option<String> {
unsafe {
- let value = CTFontDescriptorCopyAttribute(self.obj, kCTFontURLAttribute);
+ let value = CTFontDescriptorCopyAttribute(self.0, kCTFontURLAttribute);
if value.is_null() {
return None;
}
- let value: CFType = TCFType::wrap_under_get_rule(value);
+ let value = CFType::wrap_under_create_rule(value);
assert!(value.instance_of::<CFURL>());
- let url: CFURL = TCFType::wrap_under_get_rule(mem::transmute(value.as_CFTypeRef()));
- Some(format!("{:?}", url))
+ let url = CFURL::wrap_under_get_rule(mem::transmute(value.as_CFTypeRef()));
+ let path = CFString::wrap_under_create_rule(CFURLCopyFileSystemPath(
+ url.as_concrete_TypeRef(),
+ kCFURLPOSIXPathStyle,
+ )).to_string();
+ Some(path)
+ }
+ }
+
+ pub fn traits(&self) -> CTFontTraits {
+ unsafe {
+ let value = CTFontDescriptorCopyAttribute(self.0, kCTFontTraitsAttribute);
+ assert!(!value.is_null());
+ let value = CFType::wrap_under_create_rule(value);
+ assert!(value.instance_of::<CFDictionary>());
+ CFDictionary::wrap_under_get_rule(mem::transmute(value.as_CFTypeRef()))
}
}
}
pub fn new_from_attributes(attributes: &CFDictionary) -> CTFontDescriptor {
unsafe {
let result: CTFontDescriptorRef =
CTFontDescriptorCreateWithAttributes(attributes.as_concrete_TypeRef());
- TCFType::wrap_under_create_rule(result)
+ CTFontDescriptor::wrap_under_create_rule(result)
+ }
+}
+
+pub fn new_from_variations(variations: &CFDictionary) -> CTFontDescriptor {
+ unsafe {
+ let var_key = CFType::wrap_under_get_rule(mem::transmute(kCTFontVariationAttribute));
+ let var_val = CFType::wrap_under_get_rule(variations.as_CFTypeRef());
+ let attributes = CFDictionary::from_CFType_pairs(&[(var_key, var_val)]);
+ new_from_attributes(&attributes)
}
}
pub fn debug_descriptor(desc: &CTFontDescriptor) {
println!("family: {}", desc.family_name());
println!("name: {}", desc.font_name());
println!("style: {}", desc.style_name());
println!("display: {}", desc.display_name());
--- a/third_party/rust/core-text/src/lib.rs
+++ b/third_party/rust/core-text/src/lib.rs
@@ -10,15 +10,16 @@
#![crate_name = "core_text"]
#![crate_type = "rlib"]
#![allow(non_snake_case)]
extern crate foreign_types;
extern crate libc;
+#[macro_use]
extern crate core_foundation;
extern crate core_graphics;
pub mod font;
pub mod font_collection;
pub mod font_descriptor;
pub mod font_manager;
new file mode 100644
--- /dev/null
+++ b/third_party/rust/log-0.3.8/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{".travis.yml":"985cf95c79f32c65766927fd6ef5079f8c14f235ddb4213e6410d90a86a95811","Cargo.toml":"0a4a756f7ef47f5dfa221a173b21f9ec496b448aafcd9bde08d9d16935b55007","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"aa8356455efcc3d49f66e7fa394eac292c9158164dff074e32c699b64891cb4b","appveyor.yml":"c61473b8c780ad2626282ce2b2ba0ef278082b6afe151a62ff419f33eaf90221","src/lib.rs":"75b44acfc9627b821cd725649db07693a43b2e44b2fac19b79354c6d950c4038","src/macros.rs":"3953610da3ee2dc393262b753f2406d1864a1cbd74d2bd20d279e09aabfe7131","tests/filters.rs":"cc61ed41a6cd77e5aef91cc8c76216b492d8de34f00635254f3835a3d964ce22"},"package":"880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/log-0.3.8/.travis.yml
@@ -0,0 +1,29 @@
+language: rust
+sudo: false
+rust:
+ - stable
+ - beta
+ - nightly
+before_script:
+ - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
+script:
+ - cargo build --verbose
+ - ([ $TRAVIS_RUST_VERSION != nightly ] || cargo build --verbose --no-default-features)
+ - ([ $TRAVIS_RUST_VERSION != nightly ] || cargo build --verbose --features nightly)
+ - cargo test --verbose
+ - ([ $TRAVIS_RUST_VERSION != nightly ] || cargo test --verbose --no-default-features)
+ - cargo test --verbose --manifest-path env/Cargo.toml
+ - cargo test --verbose --manifest-path env/Cargo.toml --no-default-features
+ - cargo run --verbose --manifest-path tests/max_level_features/Cargo.toml
+ - cargo run --verbose --manifest-path tests/max_level_features/Cargo.toml --release
+ - ([ $TRAVIS_RUST_VERSION != nightly ] || cargo doc --no-deps --features nightly)
+ - CARGO_TARGET_DIR=target cargo doc --no-deps --manifest-path env/Cargo.toml
+after_success:
+ - travis-cargo --only nightly doc-upload
+env:
+ global:
+ secure: "VPHgnszydMudYTY8cthHj/Dmxqp7OmTiu4Sa/705Udsx+tYblTv+8WdThkClo3C/asStVcxlaRWAp91UX32/k4SfkPz17XId3Wadyt03r73ANm6ZOWY+qty+3/LINm54kuTxYUDDTbD6NaFNPFQLIE0xCpJeiXUQTlaMk6z0W3M="
+
+notifications:
+ email:
+ on_success: never
new file mode 100644
--- /dev/null
+++ b/third_party/rust/log-0.3.8/Cargo.toml
@@ -0,0 +1,49 @@
+# 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 = "log"
+version = "0.3.8"
+authors = ["The Rust Project Developers"]
+description = "A lightweight logging facade for Rust\n"
+homepage = "https://github.com/rust-lang/log"
+documentation = "https://docs.rs/log"
+readme = "README.md"
+categories = ["development-tools::debugging"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/rust-lang/log"
+
+[[test]]
+name = "filters"
+harness = false
+
+[features]
+max_level_info = []
+nightly = []
+max_level_warn = []
+release_max_level_debug = []
+release_max_level_info = []
+release_max_level_off = []
+release_max_level_error = []
+max_level_debug = []
+release_max_level_warn = []
+use_std = []
+max_level_off = []
+max_level_trace = []
+release_max_level_trace = []
+max_level_error = []
+default = ["use_std"]
+[badges.appveyor]
+repository = "alexcrichton/log"
+
+[badges.travis-ci]
+repository = "rust-lang-nursery/log"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/log-0.3.8/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/log-0.3.8/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2014 The Rust Project Developers
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/log-0.3.8/README.md
@@ -0,0 +1,177 @@
+log
+===
+
+A Rust library providing a lightweight logging *facade*.
+
+[![Build Status](https://travis-ci.org/rust-lang-nursery/log.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/log)
+[![Build status](https://ci.appveyor.com/api/projects/status/nopdjmmjt45xcrki?svg=true)](https://ci.appveyor.com/project/alexcrichton/log)
+
+* [`log` documentation](https://doc.rust-lang.org/log)
+* [`env_logger` documentation](https://doc.rust-lang.org/log/env_logger)
+
+A logging facade provides a single logging API that abstracts over the actual
+logging implementation. Libraries can use the logging API provided by this
+crate, and the consumer of those libraries can choose the logging
+implementation that is most suitable for its use case.
+
+## Usage
+
+## In libraries
+
+Libraries should link only to the `log` crate, and use the provided macros to
+log whatever information will be useful to downstream consumers:
+
+```toml
+[dependencies]
+log = "0.3"
+```
+
+```rust
+#[macro_use]
+extern crate log;
+
+pub fn shave_the_yak(yak: &Yak) {
+ trace!("Commencing yak shaving");
+
+ loop {
+ match find_a_razor() {
+ Ok(razor) => {
+ info!("Razor located: {}", razor);
+ yak.shave(razor);
+ break;
+ }
+ Err(err) => {
+ warn!("Unable to locate a razor: {}, retrying", err);
+ }
+ }
+ }
+}
+```
+
+## In executables
+
+Executables should choose a logger implementation and initialize it early in the
+runtime of the program. Logger implementations will typically include a
+function to do this. Any log messages generated before the logger is
+initialized will be ignored.
+
+The executable itself may use the `log` crate to log as well.
+
+The `env_logger` crate provides a logger implementation that mirrors the
+functionality of the old revision of the `log` crate.
+
+```toml
+[dependencies]
+log = "0.3"
+env_logger = "0.3"
+```
+
+```rust
+#[macro_use]
+extern crate log;
+extern crate env_logger;
+
+fn main() {
+ env_logger::init().unwrap();
+
+ info!("starting up");
+
+ // ...
+}
+```
+
+## In tests
+
+Tests can use the `env_logger` crate to see log messages generated during that test:
+
+```toml
+[dependencies]
+log = "0.3"
+
+[dev-dependencies]
+env_logger = "0.3"
+```
+
+```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::*;
+ extern crate env_logger;
+
+ #[test]
+ fn it_adds_one() {
+ let _ = env_logger::init();
+ info!("can log from the test too");
+ assert_eq!(3, add_one(2));
+ }
+
+ #[test]
+ fn it_handles_negative_numbers() {
+ let _ = env_logger::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::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 `LogBuilder` to change the log target:
+
+```rust
+use std::env;
+use env_logger::{LogBuilder, LogTarget};
+
+let mut builder = LogBuilder::new();
+builder.target(LogTarget::Stdout);
+if env::var("RUST_LOG").is_ok() {
+ builder.parse(&env::var("RUST_LOG").unwrap());
+}
+builder.init().unwrap();
+```
new file mode 100644
--- /dev/null
+++ b/third_party/rust/log-0.3.8/appveyor.yml
@@ -0,0 +1,18 @@
+environment:
+ matrix:
+ - TARGET: x86_64-pc-windows-msvc
+ - TARGET: i686-pc-windows-msvc
+ - TARGET: i686-pc-windows-gnu
+install:
+ - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
+ - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
+ - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
+ - SET PATH=%PATH%;C:\MinGW\bin
+ - rustc -V
+ - cargo -V
+
+build: false
+
+test_script:
+ - cargo test --verbose
+ - cargo test --manifest-path env/Cargo.toml
new file mode 100644
--- /dev/null
+++ b/third_party/rust/log-0.3.8/src/lib.rs
@@ -0,0 +1,1040 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! A lightweight logging facade.
+//!
+//! The `log` crate provides a single logging API that abstracts over the
+//! actual logging implementation. Libraries can use the logging API provided
+//! by this crate, and the consumer of those libraries can choose the logging
+//! framework that is most suitable for its use case.
+//!
+//! If no logging implementation is selected, the facade falls back to a "noop"
+//! implementation that ignores all log messages. The overhead in this case
+//! is very small - just an integer load, comparison and jump.
+//!
+//! A log request consists of a _target_, a _level_, and a _body_. A target is a
+//! string which defaults to the module path of the location of the log request,
+//! though that default may be overridden. Logger implementations typically use
+//! the target to filter requests based on some user configuration.
+//!
+//! # Use
+//!
+//! ## In libraries
+//!
+//! Libraries should link only to the `log` crate, and use the provided
+//! macros to log whatever information will be useful to downstream consumers.
+//!
+//! ### Examples
+//!
+//! ```rust
+//! # #![allow(unstable)]
+//! #[macro_use]
+//! extern crate log;
+//!
+//! # #[derive(Debug)] pub struct Yak(String);
+//! # impl Yak { fn shave(&self, _: u32) {} }
+//! # fn find_a_razor() -> Result<u32, u32> { Ok(1) }
+//! pub fn shave_the_yak(yak: &Yak) {
+//! info!(target: "yak_events", "Commencing yak shaving for {:?}", yak);
+//!
+//! loop {
+//! match find_a_razor() {
+//! Ok(razor) => {
+//! info!("Razor located: {}", razor);
+//! yak.shave(razor);
+//! break;
+//! }
+//! Err(err) => {
+//! warn!("Unable to locate a razor: {}, retrying", err);
+//! }
+//! }
+//! }
+//! }
+//! # fn main() {}
+//! ```
+//!
+//! ## In executables
+//!
+//! Executables should choose a logging framework and initialize it early in the
+//! runtime of the program. Logging frameworks will typically include a
+//! function to do this. Any log messages generated before the framework is
+//! initialized will be ignored.
+//!
+//! The executable itself may use the `log` crate to log as well.
+//!
+//! ### Warning
+//!
+//! The logging system may only be initialized once.
+//!
+//! ### Examples
+//!
+//! ```rust,ignore
+//! #[macro_use]
+//! extern crate log;
+//! extern crate env_logger;
+//!
+//! fn main() {
+//! // Select env_logger, one possible logger implementation
+//! // (see https://doc.rust-lang.org/log/env_logger/index.html)
+//! env_logger::init().unwrap();
+//!
+//! info!("starting up");
+//! error!("error: {}", 404);
+//!
+//! // ...
+//! }
+//! ```
+//!
+//! # Logger implementations
+//!
+//! Loggers implement the [`Log`] trait. Here's a very basic example that simply
+//! logs all messages at the [`Error`][level_link], [`Warn`][level_link] or
+//! [`Info`][level_link] levels to stdout:
+//!
+//! ```rust
+//! extern crate log;
+//!
+//! use log::{LogRecord, LogLevel, LogMetadata};
+//!
+//! struct SimpleLogger;
+//!
+//! impl log::Log for SimpleLogger {
+//! fn enabled(&self, metadata: &LogMetadata) -> bool {
+//! metadata.level() <= LogLevel::Info
+//! }
+//!
+//! fn log(&self, record: &LogRecord) {
+//! if self.enabled(record.metadata()) {
+//! println!("{} - {}", record.level(), record.args());
+//! }
+//! }
+//! }
+//!
+//! # fn main() {}
+//! ```
+//!
+//! Loggers are installed by calling the [`set_logger`] function. It takes a
+//! closure which is provided a [`MaxLogLevelFilter`] token and returns a
+//! [`Log`] trait object. The [`MaxLogLevelFilter`] token controls the global
+//! maximum log level. The logging facade uses this as an optimization to
+//! improve performance of log messages at levels that are disabled. In the
+//! case of our example logger, we'll want to set the maximum log level to
+//! [`Info`][level_link], since we ignore any [`Debug`][level_link] or
+//! [`Trace`][level_link] level log messages. A logging framework should
+//! provide a function that wraps a call to [`set_logger`], handling
+//! initialization of the logger:
+//!
+//! ```rust
+//! # extern crate log;
+//! # use log::{LogLevel, LogLevelFilter, SetLoggerError, LogMetadata};
+//! # struct SimpleLogger;
+//! # impl log::Log for SimpleLogger {
+//! # fn enabled(&self, _: &LogMetadata) -> bool { false }
+//! # fn log(&self, _: &log::LogRecord) {}
+//! # }
+//! # fn main() {}
+//! # #[cfg(feature = "use_std")]
+//! pub fn init() -> Result<(), SetLoggerError> {
+//! log::set_logger(|max_log_level| {
+//! max_log_level.set(LogLevelFilter::Info);
+//! Box::new(SimpleLogger)
+//! })
+//! }
+//! ```
+//!
+//! # Use with `no_std`
+//!
+//! To use the `log` crate without depending on `libstd`, you need to specify
+//! `default-features = false` when specifying the dependency in `Cargo.toml`.
+//! This makes no difference to libraries using `log` since the logging API
+//! remains the same. However executables will need to use the [`set_logger_raw`]
+//! function to initialize a logger and the [`shutdown_logger_raw`] function to
+//! shut down the global logger before exiting:
+//!
+//! ```rust
+//! # extern crate log;
+//! # use log::{LogLevel, LogLevelFilter, SetLoggerError, ShutdownLoggerError,
+//! # LogMetadata};
+//! # struct SimpleLogger;
+//! # impl log::Log for SimpleLogger {
+//! # fn enabled(&self, _: &LogMetadata) -> bool { false }
+//! # fn log(&self, _: &log::LogRecord) {}
+//! # }
+//! # impl SimpleLogger {
+//! # fn flush(&self) {}
+//! # }
+//! # fn main() {}
+//! pub fn init() -> Result<(), SetLoggerError> {
+//! unsafe {
+//! log::set_logger_raw(|max_log_level| {
+//! static LOGGER: SimpleLogger = SimpleLogger;
+//! max_log_level.set(LogLevelFilter::Info);
+//! &SimpleLogger
+//! })
+//! }
+//! }
+//! pub fn shutdown() -> Result<(), ShutdownLoggerError> {
+//! log::shutdown_logger_raw().map(|logger| {
+//! let logger = unsafe { &*(logger as *const SimpleLogger) };
+//! logger.flush();
+//! })
+//! }
+//! ```
+//!
+//! [`Log`]: trait.Log.html
+//! [level_link]: enum.LogLevel.html
+//! [`set_logger`]: fn.set_logger.html
+//! [`MaxLogLevelFilter`]: struct.MaxLogLevelFilter.html
+//! [`set_logger_raw`]: fn.set_logger_raw.html
+//! [`shutdown_logger_raw`]: fn.shutdown_logger_raw.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/favicon.ico",
+ html_root_url = "https://doc.rust-lang.org/log/")]
+#![warn(missing_docs)]
+#![deny(missing_debug_implementations)]
+#![cfg_attr(feature = "nightly", feature(panic_handler))]
+
+#![cfg_attr(not(feature = "use_std"), no_std)]
+
+// 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"))]
+
+#[cfg(not(feature = "use_std"))]
+extern crate core as std;
+
+use std::cmp;
+#[cfg(feature = "use_std")]
+use std::error;
+use std::fmt;
+use std::mem;
+use std::ops::Deref;
+use std::str::FromStr;
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+#[macro_use]
+mod macros;
+
+// The setup here is a bit weird to make shutdown_logger_raw work.
+//
+// There are four different states that we care about: the logger's
+// uninitialized, the logger's initializing (set_logger's been called but
+// LOGGER hasn't actually been set yet), the logger's active, or the logger is
+// shut down after calling shutdown_logger_raw.
+//
+// The LOGGER static holds a pointer to the global logger. It is protected by
+// the STATE static which determines whether LOGGER has been initialized yet.
+//
+// The shutdown_logger_raw routine needs to make sure that no threads are
+// actively logging before it returns. The number of actively logging threads is
+// tracked in the REFCOUNT static. The routine first sets STATE back to
+// INITIALIZING. All logging calls past that point will immediately return
+// without accessing the logger. At that point, the at_exit routine just waits
+// for the refcount to reach 0 before deallocating the logger. Note that the
+// refcount does not necessarily monotonically decrease at this point, as new
+// log calls still increment and decrement it, but the interval in between is
+// small enough that the wait is really just for the active log calls to finish.
+
+static mut LOGGER: *const Log = &NopLogger;
+static STATE: AtomicUsize = ATOMIC_USIZE_INIT;
+static REFCOUNT: AtomicUsize = ATOMIC_USIZE_INIT;
+
+const UNINITIALIZED: usize = 0;
+const INITIALIZING: usize = 1;
+const INITIALIZED: usize = 2;
+
+static MAX_LOG_LEVEL_FILTER: AtomicUsize = ATOMIC_USIZE_INIT;
+
+static LOG_LEVEL_NAMES: [&'static str; 6] = ["OFF", "ERROR", "WARN", "INFO",
+ "DEBUG", "TRACE"];
+
+/// An enum representing the available verbosity levels of the logging framework.
+///
+/// Typical usage includes: checking if a certain `LogLevel` is enabled with
+/// [`log_enabled!`](macro.log_enabled.html), specifying the `LogLevel` of
+/// [`log!`](macro.log.html), and comparing a `LogLevel` directly to a
+/// [`LogLevelFilter`](enum.LogLevelFilter.html).
+#[repr(usize)]
+#[derive(Copy, Eq, Debug, Hash)]
+pub enum LogLevel {
+ /// The "error" level.
+ ///
+ /// Designates very serious errors.
+ Error = 1, // This way these line up with the discriminants for LogLevelFilter below
+ /// The "warn" level.
+ ///
+ /// Designates hazardous situations.
+ Warn,
+ /// The "info" level.
+ ///
+ /// Designates useful information.
+ Info,
+ /// The "debug" level.
+ ///
+ /// Designates lower priority information.
+ Debug,
+ /// The "trace" level.
+ ///
+ /// Designates very low priority, often extremely verbose, information.
+ Trace,
+}
+
+impl Clone for LogLevel {
+ #[inline]
+ fn clone(&self) -> LogLevel {
+ *self
+ }
+}
+
+impl PartialEq for LogLevel {
+ #[inline]
+ fn eq(&self, other: &LogLevel) -> bool {
+ *self as usize == *other as usize
+ }
+}
+
+impl PartialEq<LogLevelFilter> for LogLevel {
+ #[inline]
+ fn eq(&self, other: &LogLevelFilter) -> bool {
+ *self as usize == *other as usize
+ }
+}
+
+impl PartialOrd for LogLevel {
+ #[inline]
+ fn partial_cmp(&self, other: &LogLevel) -> Option<cmp::Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl PartialOrd<LogLevelFilter> for LogLevel {
+ #[inline]
+ fn partial_cmp(&self, other: &LogLevelFilter) -> Option<cmp::Ordering> {
+ Some((*self as usize).cmp(&(*other as usize)))
+ }
+}
+
+impl Ord for LogLevel {
+ #[inline]
+ fn cmp(&self, other: &LogLevel) -> cmp::Ordering {
+ (*self as usize).cmp(&(*other as usize))
+ }
+}
+
+fn ok_or<T, E>(t: Option<T>, e: E) -> Result<T, E> {
+ match t {
+ Some(t) => Ok(t),
+ None => Err(e),
+ }
+}
+
+// Reimplemented here because std::ascii is not available in libcore
+fn eq_ignore_ascii_case(a: &str, b: &str) -> bool {
+ fn to_ascii_uppercase(c: u8) -> u8 {
+ if c >= b'a' && c <= b'z' {
+ c - b'a' + b'A'
+ } else {
+ c
+ }
+ }
+
+ if a.len() == b.len() {
+ a.bytes()
+ .zip(b.bytes())
+ .all(|(a, b)| to_ascii_uppercase(a) == to_ascii_uppercase(b))
+ } else {
+ false
+ }
+}
+
+impl FromStr for LogLevel {
+ type Err = ();
+ fn from_str(level: &str) -> Result<LogLevel, ()> {
+ ok_or(LOG_LEVEL_NAMES.iter()
+ .position(|&name| eq_ignore_ascii_case(name, level))
+ .into_iter()
+ .filter(|&idx| idx != 0)
+ .map(|idx| LogLevel::from_usize(idx).unwrap())
+ .next(), ())
+ }
+}
+
+impl fmt::Display for LogLevel {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.pad(LOG_LEVEL_NAMES[*self as usize])
+ }
+}
+
+impl LogLevel {
+ fn from_usize(u: usize) -> Option<LogLevel> {
+ match u {
+ 1 => Some(LogLevel::Error),
+ 2 => Some(LogLevel::Warn),
+ 3 => Some(LogLevel::Info),
+ 4 => Some(LogLevel::Debug),
+ 5 => Some(LogLevel::Trace),
+ _ => None
+ }
+ }
+
+ /// Returns the most verbose logging level.
+ #[inline]
+ pub fn max() -> LogLevel {
+ LogLevel::Trace
+ }
+
+ /// Converts the `LogLevel` to the equivalent `LogLevelFilter`.
+ #[inline]
+ pub fn to_log_level_filter(&self) -> LogLevelFilter {
+ LogLevelFilter::from_usize(*self as usize).unwrap()
+ }
+}
+
+/// An enum representing the available verbosity level filters of the logging
+/// framework.
+///
+/// A `LogLevelFilter` may be compared directly to a [`LogLevel`](enum.LogLevel.html).
+/// Use this type to [`get()`](struct.MaxLogLevelFilter.html#method.get) and
+/// [`set()`](struct.MaxLogLevelFilter.html#method.set) the
+/// [`MaxLogLevelFilter`](struct.MaxLogLevelFilter.html), or to match with the getter
+/// [`max_log_level()`](fn.max_log_level.html).
+#[repr(usize)]
+#[derive(Copy, Eq, Debug, Hash)]
+pub enum LogLevelFilter {
+ /// A level lower than all log levels.
+ Off,
+ /// Corresponds to the `Error` log level.
+ Error,
+ /// Corresponds to the `Warn` log level.
+ Warn,
+ /// Corresponds to the `Info` log level.
+ Info,
+ /// Corresponds to the `Debug` log level.
+ Debug,
+ /// Corresponds to the `Trace` log level.
+ Trace,
+}
+
+// Deriving generates terrible impls of these traits
+
+impl Clone for LogLevelFilter {
+ #[inline]
+ fn clone(&self) -> LogLevelFilter {
+ *self
+ }
+}
+
+impl PartialEq for LogLevelFilter {
+ #[inline]
+ fn eq(&self, other: &LogLevelFilter) -> bool {
+ *self as usize == *other as usize
+ }
+}
+
+impl PartialEq<LogLevel> for LogLevelFilter {
+ #[inline]
+ fn eq(&self, other: &LogLevel) -> bool {
+ other.eq(self)
+ }
+}
+
+impl PartialOrd for LogLevelFilter {
+ #[inline]
+ fn partial_cmp(&self, other: &LogLevelFilter) -> Option<cmp::Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl PartialOrd<LogLevel> for LogLevelFilter {
+ #[inline]
+ fn partial_cmp(&self, other: &LogLevel) -> Option<cmp::Ordering> {
+ other.partial_cmp(self).map(|x| x.reverse())
+ }
+}
+
+impl Ord for LogLevelFilter {
+ #[inline]
+ fn cmp(&self, other: &LogLevelFilter) -> cmp::Ordering {
+ (*self as usize).cmp(&(*other as usize))
+ }
+}
+
+impl FromStr for LogLevelFilter {
+ type Err = ();
+ fn from_str(level: &str) -> Result<LogLevelFilter, ()> {
+ ok_or(LOG_LEVEL_NAMES.iter()
+ .position(|&name| eq_ignore_ascii_case(name, level))
+ .map(|p| LogLevelFilter::from_usize(p).unwrap()), ())
+ }
+}
+
+impl fmt::Display for LogLevelFilter {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "{}", LOG_LEVEL_NAMES[*self as usize])
+ }
+}
+
+impl LogLevelFilter {
+ fn from_usize(u: usize) -> Option<LogLevelFilter> {
+ match u {
+ 0 => Some(LogLevelFilter::Off),
+ 1 => Some(LogLevelFilter::Error),
+ 2 => Some(LogLevelFilter::Warn),
+ 3 => Some(LogLevelFilter::Info),
+ 4 => Some(LogLevelFilter::Debug),
+ 5 => Some(LogLevelFilter::Trace),
+ _ => None
+ }
+ }
+ /// Returns the most verbose logging level filter.
+ #[inline]
+ pub fn max() -> LogLevelFilter {
+ LogLevelFilter::Trace
+ }
+
+ /// Converts `self` to the equivalent `LogLevel`.
+ ///
+ /// Returns `None` if `self` is `LogLevelFilter::Off`.
+ #[inline]
+ pub fn to_log_level(&self) -> Option<LogLevel> {
+ LogLevel::from_usize(*self as usize)
+ }
+}
+
+/// The "payload" of a log message. This structure is primarily used as a
+/// parameter in the [`log`] method of the [`Log`] trait.
+///
+/// [`log`]: trait.Log.html#tymethod.log
+/// [`Log`]: trait.Log.html
+#[derive(Debug)]
+pub struct LogRecord<'a> {
+ metadata: LogMetadata<'a>,
+ location: &'a LogLocation,
+ args: fmt::Arguments<'a>,
+}
+
+impl<'a> LogRecord<'a> {
+ /// The message body.
+ pub fn args(&self) -> &fmt::Arguments<'a> {
+ &self.args
+ }
+
+ /// Metadata about the log directive.
+ pub fn metadata(&self) -> &LogMetadata {
+ &self.metadata
+ }
+
+ /// The location of the log directive.
+ pub fn location(&self) -> &LogLocation {
+ self.location
+ }
+
+ /// The verbosity level of the message.
+ pub fn level(&self) -> LogLevel {
+ self.metadata.level()
+ }
+
+ /// The name of the target of the directive.
+ pub fn target(&self) -> &str {
+ self.metadata.target()
+ }
+}
+
+/// Metadata about a log message.
+#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
+pub struct LogMetadata<'a> {
+ level: LogLevel,
+ target: &'a str,
+}
+
+impl<'a> LogMetadata<'a> {
+ /// The verbosity level of the message.
+ pub fn level(&self) -> LogLevel {
+ self.level
+ }
+
+ /// The name of the target of the directive.
+ pub fn target(&self) -> &str {
+ self.target
+ }
+}
+
+/// A trait encapsulating the operations required of a logger
+pub trait Log: Sync+Send {
+ /// Determines if a log message with the specified metadata would be
+ /// logged.
+ ///
+ /// This is used by the `log_enabled!` macro to allow callers to avoid
+ /// expensive computation of log message arguments if the message would be
+ /// discarded anyway.
+ fn enabled(&self, metadata: &LogMetadata) -> bool;
+
+ /// Logs the `LogRecord`.
+ ///
+ /// Note that `enabled` is *not* necessarily called before this method.
+ /// Implementations of `log` should perform all necessary filtering
+ /// internally.
+ fn log(&self, record: &LogRecord);
+}
+
+// Just used as a dummy initial value for LOGGER
+struct NopLogger;
+
+impl Log for NopLogger {
+ fn enabled(&self, _: &LogMetadata) -> bool { false }
+
+ fn log(&self, _: &LogRecord) {}
+}
+
+/// The location of a log message.
+///
+/// # Warning
+///
+/// The fields of this struct are public so that they may be initialized by the
+/// `log!` macro. They are subject to change at any time and should never be
+/// accessed directly.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
+pub struct LogLocation {
+ #[doc(hidden)]
+ pub __module_path: &'static str,
+ #[doc(hidden)]
+ pub __file: &'static str,
+ #[doc(hidden)]
+ pub __line: u32,
+}
+
+impl LogLocation {
+ /// The module path of the message.
+ pub fn module_path(&self) -> &str {
+ self.__module_path
+ }
+
+ /// The source file containing the message.
+ pub fn file(&self) -> &str {
+ self.__file
+ }
+
+ /// The line containing the message.
+ pub fn line(&self) -> u32 {
+ self.__line
+ }
+}
+
+/// A token providing read and write access to the global maximum log level
+/// filter.
+///
+/// The maximum log level is used as an optimization to avoid evaluating log
+/// messages that will be ignored by the logger. Any message with a level
+/// higher than the maximum log level filter will be ignored. A logger should
+/// make sure to keep the maximum log level filter in sync with its current
+/// configuration.
+#[allow(missing_copy_implementations)]
+pub struct MaxLogLevelFilter(());
+
+impl fmt::Debug for MaxLogLevelFilter {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "MaxLogLevelFilter")
+ }
+}
+
+impl MaxLogLevelFilter {
+ /// Gets the current maximum log level filter.
+ pub fn get(&self) -> LogLevelFilter {
+ max_log_level()
+ }
+
+ /// Sets the maximum log level.
+ pub fn set(&self, level: LogLevelFilter) {
+ MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::SeqCst)
+ }
+}
+
+/// Returns the current maximum log level.
+///
+/// The `log!`, `error!`, `warn!`, `info!`, `debug!`, and `trace!` macros check
+/// this value and discard any message logged at a higher level. The maximum
+/// log level is set by the `MaxLogLevel` token passed to loggers.
+#[inline(always)]
+pub fn max_log_level() -> LogLevelFilter {
+ unsafe { mem::transmute(MAX_LOG_LEVEL_FILTER.load(Ordering::Relaxed)) }
+}
+
+/// Sets the global logger.
+///
+/// The `make_logger` closure is passed a `MaxLogLevel` object, which the
+/// logger should use to keep the global maximum log level in sync with the
+/// highest log level that the logger will not ignore.
+///
+/// This function may only be called once in the lifetime of a program. Any log
+/// events that occur before the call to `set_logger` completes will be
+/// ignored.
+///
+/// This function does not typically need to be called manually. Logger
+/// implementations should provide an initialization method that calls
+/// `set_logger` internally.
+///
+/// Requires the `use_std` feature (enabled by default).
+#[cfg(feature = "use_std")]
+pub fn set_logger<M>(make_logger: M) -> Result<(), SetLoggerError>
+ where M: FnOnce(MaxLogLevelFilter) -> Box<Log> {
+ unsafe { set_logger_raw(|max_level| mem::transmute(make_logger(max_level))) }
+}
+
+/// Sets the global logger from a raw pointer.
+///
+/// This function is similar to `set_logger` except that it is usable in
+/// `no_std` code.
+///
+/// The `make_logger` closure is passed a `MaxLogLevel` object, which the
+/// logger should use to keep the global maximum log level in sync with the
+/// highest log level that the logger will not ignore.
+///
+/// This function may only be called once in the lifetime of a program. Any log
+/// events that occur before the call to `set_logger_raw` completes will be
+/// ignored.
+///
+/// This function does not typically need to be called manually. Logger
+/// implementations should provide an initialization method that calls
+/// `set_logger_raw` internally.
+///
+/// # Safety
+///
+/// The pointer returned by `make_logger` must remain valid for the entire
+/// duration of the program or until `shutdown_logger_raw` is called. In
+/// addition, `shutdown_logger` *must not* be called after this function.
+pub unsafe fn set_logger_raw<M>(make_logger: M) -> Result<(), SetLoggerError>
+ where M: FnOnce(MaxLogLevelFilter) -> *const Log {
+ if STATE.compare_and_swap(UNINITIALIZED, INITIALIZING,
+ Ordering::SeqCst) != UNINITIALIZED {
+ return Err(SetLoggerError(()));
+ }
+
+ LOGGER = make_logger(MaxLogLevelFilter(()));
+ STATE.store(INITIALIZED, Ordering::SeqCst);
+ Ok(())
+}
+
+/// Shuts down the global logger.
+///
+/// This function may only be called once in the lifetime of a program, and may
+/// not be called before `set_logger`. Once the global logger has been shut
+/// down, it can no longer be re-initialized by `set_logger`. Any log events
+/// that occur after the call to `shutdown_logger` completes will be ignored.
+///
+/// The logger that was originally created by the call to to `set_logger` is
+/// returned on success. At that point it is guaranteed that no other threads
+/// are concurrently accessing the logger object.
+#[cfg(feature = "use_std")]
+pub fn shutdown_logger() -> Result<Box<Log>, ShutdownLoggerError> {
+ shutdown_logger_raw().map(|l| unsafe { mem::transmute(l) })
+}
+
+/// Shuts down the global logger.
+///
+/// This function is similar to `shutdown_logger` except that it is usable in
+/// `no_std` code.
+///
+/// This function may only be called once in the lifetime of a program, and may
+/// not be called before `set_logger_raw`. Once the global logger has been shut
+/// down, it can no longer be re-initialized by `set_logger_raw`. Any log
+/// events that occur after the call to `shutdown_logger_raw` completes will be
+/// ignored.
+///
+/// The pointer that was originally passed to `set_logger_raw` is returned on
+/// success. At that point it is guaranteed that no other threads are
+/// concurrently accessing the logger object.
+pub fn shutdown_logger_raw() -> Result<*const Log, ShutdownLoggerError> {
+ // Set the global log level to stop other thread from logging
+ MAX_LOG_LEVEL_FILTER.store(0, Ordering::SeqCst);
+
+ // Set to INITIALIZING to prevent re-initialization after
+ if STATE.compare_and_swap(INITIALIZED, INITIALIZING,
+ Ordering::SeqCst) != INITIALIZED {
+ return Err(ShutdownLoggerError(()));
+ }
+
+ while REFCOUNT.load(Ordering::SeqCst) != 0 {
+ // FIXME add a sleep here when it doesn't involve timers
+ }
+
+ unsafe {
+ let logger = LOGGER;
+ LOGGER = &NopLogger;
+ Ok(logger)
+ }
+}
+
+/// The type returned by `set_logger` if `set_logger` has already been called.
+#[allow(missing_copy_implementations)]
+#[derive(Debug)]
+pub struct SetLoggerError(());
+
+impl fmt::Display for SetLoggerError {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "attempted to set a logger after the logging system \
+ was already initialized")
+ }
+}
+
+// The Error trait is not available in libcore
+#[cfg(feature = "use_std")]
+impl error::Error for SetLoggerError {
+ fn description(&self) -> &str { "set_logger() called multiple times" }
+}
+
+/// The type returned by `shutdown_logger_raw` if `shutdown_logger_raw` has
+/// already been called or if `set_logger_raw` has not been called yet.
+#[allow(missing_copy_implementations)]
+#[derive(Debug)]
+pub struct ShutdownLoggerError(());
+
+impl fmt::Display for ShutdownLoggerError {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "attempted to shut down the logger without an active logger")
+ }
+}
+
+// The Error trait is not available in libcore
+#[cfg(feature = "use_std")]
+impl error::Error for ShutdownLoggerError {
+ fn description(&self) -> &str { "shutdown_logger() called without an active logger" }
+}
+
+/// Deprecated
+///
+/// Use https://crates.io/crates/log-panics instead.
+#[cfg(all(feature = "nightly", feature = "use_std"))]
+pub fn log_panics() {
+ std::panic::set_hook(Box::new(panic::log));
+}
+
+// inner module so that the reporting module is log::panic instead of log
+#[cfg(all(feature = "nightly", feature = "use_std"))]
+mod panic {
+ use std::panic::PanicInfo;
+ use std::thread;
+
+ pub fn log(info: &PanicInfo) {
+ let thread = thread::current();
+ let thread = thread.name().unwrap_or("<unnamed>");
+
+ let msg = match info.payload().downcast_ref::<&'static str>() {
+ Some(s) => *s,
+ None => match info.payload().downcast_ref::<String>() {
+ Some(s) => &s[..],
+ None => "Box<Any>",
+ }
+ };
+
+ match info.location() {
+ Some(location) => {
+ error!("thread '{}' panicked at '{}': {}:{}",
+ thread,
+ msg,
+ location.file(),
+ location.line())
+ }
+ None => error!("thread '{}' panicked at '{}'", thread, msg),
+ }
+ }
+}
+
+struct LoggerGuard(&'static Log);
+
+impl Drop for LoggerGuard {
+ fn drop(&mut self) {
+ REFCOUNT.fetch_sub(1, Ordering::SeqCst);
+ }
+}
+
+impl Deref for LoggerGuard {
+ type Target = Log;
+
+ fn deref(&self) -> &(Log + 'static) {
+ self.0
+ }
+}
+
+fn logger() -> Option<LoggerGuard> {
+ REFCOUNT.fetch_add(1, Ordering::SeqCst);
+ if STATE.load(Ordering::SeqCst) != INITIALIZED {
+ REFCOUNT.fetch_sub(1, Ordering::SeqCst);
+ None
+ } else {
+ Some(LoggerGuard(unsafe { &*LOGGER }))
+ }
+}
+
+// WARNING
+// This is not considered part of the crate's public API. It is subject to
+// change at any time.
+#[doc(hidden)]
+pub fn __enabled(level: LogLevel, target: &str) -> bool {
+ if let Some(logger) = logger() {
+ logger.enabled(&LogMetadata { level: level, target: target })
+ } else {
+ false
+ }
+}
+
+// WARNING
+// This is not considered part of the crate's public API. It is subject to
+// change at any time.
+#[doc(hidden)]
+pub fn __log(level: LogLevel, target: &str, loc: &LogLocation,
+ args: fmt::Arguments) {
+ if let Some(logger) = logger() {
+ let record = LogRecord {
+ metadata: LogMetadata {
+ level: level,
+ target: target,
+ },
+ location: loc,
+ args: args
+ };
+ logger.log(&record)
+ }
+}
+
+// WARNING
+// This is not considered part of the crate's public API. It is subject to
+// change at any time.
+#[inline(always)]
+#[doc(hidden)]
+pub fn __static_max_level() -> LogLevelFilter {
+ if !cfg!(debug_assertions) {
+ // This is a release build. Check `release_max_level_*` first.
+ if cfg!(feature = "release_max_level_off") {
+ return LogLevelFilter::Off
+ } else if cfg!(feature = "release_max_level_error") {
+ return LogLevelFilter::Error
+ } else if cfg!(feature = "release_max_level_warn") {
+ return LogLevelFilter::Warn
+ } else if cfg!(feature = "release_max_level_info") {
+ return LogLevelFilter::Info
+ } else if cfg!(feature = "release_max_level_debug") {
+ return LogLevelFilter::Debug
+ } else if cfg!(feature = "release_max_level_trace") {
+ return LogLevelFilter::Trace
+ }
+ }
+ if cfg!(feature = "max_level_off") {
+ LogLevelFilter::Off
+ } else if cfg!(feature = "max_level_error") {
+ LogLevelFilter::Error
+ } else if cfg!(feature = "max_level_warn") {
+ LogLevelFilter::Warn
+ } else if cfg!(feature = "max_level_info") {
+ LogLevelFilter::Info
+ } else if cfg!(feature = "max_level_debug") {
+ LogLevelFilter::Debug
+ } else {
+ LogLevelFilter::Trace
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ extern crate std;
+ use tests::std::string::ToString;
+ use super::{LogLevel, LogLevelFilter};
+
+ #[test]
+ fn test_loglevelfilter_from_str() {
+ let tests = [
+ ("off", Ok(LogLevelFilter::Off)),
+ ("error", Ok(LogLevelFilter::Error)),
+ ("warn", Ok(LogLevelFilter::Warn)),
+ ("info", Ok(LogLevelFilter::Info)),
+ ("debug", Ok(LogLevelFilter::Debug)),
+ ("trace", Ok(LogLevelFilter::Trace)),
+ ("OFF", Ok(LogLevelFilter::Off)),
+ ("ERROR", Ok(LogLevelFilter::Error)),
+ ("WARN", Ok(LogLevelFilter::Warn)),
+ ("INFO", Ok(LogLevelFilter::Info)),
+ ("DEBUG", Ok(LogLevelFilter::Debug)),
+ ("TRACE", Ok(LogLevelFilter::Trace)),
+ ("asdf", Err(())),
+ ];
+ for &(s, ref expected) in &tests {
+ assert_eq!(expected, &s.parse());
+ }
+ }
+
+ #[test]
+ fn test_loglevel_from_str() {
+ let tests = [
+ ("OFF", Err(())),
+ ("error", Ok(LogLevel::Error)),
+ ("warn", Ok(LogLevel::Warn)),
+ ("info", Ok(LogLevel::Info)),
+ ("debug", Ok(LogLevel::Debug)),
+ ("trace", Ok(LogLevel::Trace)),
+ ("ERROR", Ok(LogLevel::Error)),
+ ("WARN", Ok(LogLevel::Warn)),
+ ("INFO", Ok(LogLevel::Info)),
+ ("DEBUG", Ok(LogLevel::Debug)),
+ ("TRACE", Ok(LogLevel::Trace)),
+ ("asdf", Err(())),
+ ];
+ for &(s, ref expected) in &tests {
+ assert_eq!(expected, &s.parse());
+ }
+ }
+
+ #[test]
+ fn test_loglevel_show() {
+ assert_eq!("INFO", LogLevel::Info.to_string());
+ assert_eq!("ERROR", LogLevel::Error.to_string());
+ }
+
+ #[test]
+ fn test_loglevelfilter_show() {
+ assert_eq!("OFF", LogLevelFilter::Off.to_string());
+ assert_eq!("ERROR", LogLevelFilter::Error.to_string());
+ }
+
+ #[test]
+ fn test_cross_cmp() {
+ assert!(LogLevel::Debug > LogLevelFilter::Error);
+ assert!(LogLevelFilter::Warn < LogLevel::Trace);
+ assert!(LogLevelFilter::Off < LogLevel::Error);
+ }
+
+ #[test]
+ fn test_cross_eq() {
+ assert!(LogLevel::Error == LogLevelFilter::Error);
+ assert!(LogLevelFilter::Off != LogLevel::Error);
+ assert!(LogLevel::Trace == LogLevelFilter::Trace);
+ }
+
+ #[test]
+ fn test_to_log_level() {
+ assert_eq!(Some(LogLevel::Error), LogLevelFilter::Error.to_log_level());
+ assert_eq!(None, LogLevelFilter::Off.to_log_level());
+ assert_eq!(Some(LogLevel::Debug), LogLevelFilter::Debug.to_log_level());
+ }
+
+ #[test]
+ fn test_to_log_level_filter() {
+ assert_eq!(LogLevelFilter::Error, LogLevel::Error.to_log_level_filter());
+ assert_eq!(LogLevelFilter::Trace, LogLevel::Trace.to_log_level_filter());
+ }
+
+ #[test]
+ #[cfg(feature = "use_std")]
+ fn test_error_trait() {
+ use std::error::Error;
+ use super::SetLoggerError;
+ let e = SetLoggerError(());
+ assert_eq!(e.description(), "set_logger() called multiple times");
+ }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/log-0.3.8/src/macros.rs
@@ -0,0 +1,243 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+/// The standard logging macro.
+///
+/// This macro will generically log with the specified `LogLevel` and `format!`
+/// based argument list.
+///
+/// The `max_level_*` features can be used to statically disable logging at
+/// various levels.
+///
+/// # Examples
+///
+/// ```rust
+/// # #[macro_use]
+/// # extern crate log;
+/// use log::LogLevel;
+///
+/// # fn main() {
+/// let data = (42, "Forty-two");
+/// let private_data = "private";
+///
+/// log!(LogLevel::Error, "Received errors: {}, {}", data.0, data.1);
+/// log!(target: "app_events", LogLevel::Warn, "App warning: {}, {}, {}",
+/// data.0, data.1, private_data);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! log {
+ (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
+ static _LOC: $crate::LogLocation = $crate::LogLocation {
+ __line: line!(),
+ __file: file!(),
+ __module_path: module_path!(),
+ };
+ let lvl = $lvl;
+ if lvl <= $crate::__static_max_level() && lvl <= $crate::max_log_level() {
+ $crate::__log(lvl, $target, &_LOC, format_args!($($arg)+))
+ }
+ });
+ ($lvl:expr, $($arg:tt)+) => (log!(target: module_path!(), $lvl, $($arg)+))
+}
+
+/// Logs a message at the error level.
+///
+/// Logging at this level is disabled if the `max_level_off` feature is present.
+///
+/// # Examples
+///
+/// ```rust
+/// # #[macro_use]
+/// # extern crate log;
+/// # fn main() {
+/// let (err_info, port) = ("No connection", 22);
+///
+/// error!("Error: {} on port {}", err_info, port);
+/// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! error {
+ (target: $target:expr, $($arg:tt)*) => (
+ log!(target: $target, $crate::LogLevel::Error, $($arg)*);
+ );
+ ($($arg:tt)*) => (
+ log!($crate::LogLevel::Error, $($arg)*);
+ )
+}
+
+/// Logs a message at the warn level.
+///
+/// Logging at this level is disabled if any of the following features are
+/// present: `max_level_off` or `max_level_error`.
+///
+/// When building in release mode (i.e., without the `debug_assertions` option),
+/// logging at this level is also disabled if any of the following features are
+/// present: `release_max_level_off` or `max_level_error`.
+///
+/// # Examples
+///
+/// ```rust
+/// # #[macro_use]
+/// # extern crate log;
+/// # fn main() {
+/// let warn_description = "Invalid Input";
+///
+/// warn!("Warning! {}!", warn_description);
+/// warn!(target: "input_events", "App received warning: {}", warn_description);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! warn {
+ (target: $target:expr, $($arg:tt)*) => (
+ log!(target: $target, $crate::LogLevel::Warn, $($arg)*);
+ );
+ ($($arg:tt)*) => (
+ log!($crate::LogLevel::Warn, $($arg)*);
+ )
+}
+
+/// Logs a message at the info level.
+///
+/// Logging at this level is disabled if any of the following features are
+/// present: `max_level_off`, `max_level_error`, or `max_level_warn`.
+///
+/// When building in release mode (i.e., without the `debug_assertions` option),
+/// logging at this level is also disabled if any of the following features are
+/// present: `release_max_level_off`, `release_max_level_error`, or
+/// `release_max_level_warn`.
+///
+/// # Examples
+///
+/// ```rust
+/// # #[macro_use]
+/// # extern crate log;
+/// # fn main() {
+/// # struct Connection { port: u32, speed: f32 }
+/// let conn_info = Connection { port: 40, speed: 3.20 };
+///
+/// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed);
+/// info!(target: "connection_events", "Successfull connection, port: {}, speed: {}",
+/// conn_info.port, conn_info.speed);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! info {
+ (target: $target:expr, $($arg:tt)*) => (
+ log!(target: $target, $crate::LogLevel::Info, $($arg)*);
+ );
+ ($($arg:tt)*) => (
+ log!($crate::LogLevel::Info, $($arg)*);
+ )
+}
+
+/// Logs a message at the debug level.
+///
+/// Logging at this level is disabled if any of the following features are
+/// present: `max_level_off`, `max_level_error`, `max_level_warn`, or
+/// `max_level_info`.
+///
+/// When building in release mode (i.e., without the `debug_assertions` option),
+/// logging at this level is also disabled if any of the following features are
+/// present: `release_max_level_off`, `release_max_level_error`,
+/// `release_max_level_warn`, or `release_max_level_info`.
+///
+/// # Examples
+///
+/// ```rust
+/// # #[macro_use]
+/// # extern crate log;
+/// # fn main() {
+/// # struct Position { x: f32, y: f32 }
+/// let pos = Position { x: 3.234, y: -1.223 };
+///
+/// debug!("New position: x: {}, y: {}", pos.x, pos.y);
+/// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! debug {
+ (target: $target:expr, $($arg:tt)*) => (
+ log!(target: $target, $crate::LogLevel::Debug, $($arg)*);
+ );
+ ($($arg:tt)*) => (
+ log!($crate::LogLevel::Debug, $($arg)*);
+ )
+}
+
+/// Logs a message at the trace level.
+///
+/// Logging at this level is disabled if any of the following features are
+/// present: `max_level_off`, `max_level_error`, `max_level_warn`,
+/// `max_level_info`, or `max_level_debug`.
+///
+/// When building in release mode (i.e., without the `debug_assertions` option),
+/// logging at this level is also disabled if any of the following features are
+/// present: `release_max_level_off`, `release_max_level_error`,
+/// `release_max_level_warn`, `release_max_level_info`, or
+/// `release_max_level_debug`.
+///
+/// # Examples
+///
+/// ```rust
+/// # #[macro_use]
+/// # extern crate log;
+/// # fn main() {
+/// # struct Position { x: f32, y: f32 }
+/// let pos = Position { x: 3.234, y: -1.223 };
+///
+/// trace!("Position is: x: {}, y: {}", pos.x, pos.y);
+/// trace!(target: "app_events", "x is {} and y is {}",
+/// if pos.x >= 0.0 { "positive" } else { "negative" },
+/// if pos.y >= 0.0 { "positive" } else { "negative" });
+/// # }
+/// ```
+#[macro_export]
+macro_rules! trace {
+ (target: $target:expr, $($arg:tt)*) => (
+ log!(target: $target, $crate::LogLevel::Trace, $($arg)*);
+ );
+ ($($arg:tt)*) => (
+ log!($crate::LogLevel::Trace, $($arg)*);
+ )
+}
+
+/// Determines if a message logged at the specified level in that module will
+/// be logged.
+///
+/// This can be used to avoid expensive computation of log message arguments if
+/// the message would be ignored anyway.
+///
+/// # Examples
+///
+/// ```rust
+/// # #[macro_use]
+/// # extern crate log;
+/// use log::LogLevel::Debug;
+///
+/// # fn foo() {
+/// if log_enabled!(Debug) {
+/// let data = expensive_call();
+/// debug!("expensive debug data: {} {}", data.x, data.y);
+/// }
+/// # }
+/// # struct Data { x: u32, y: u32 }
+/// # fn expensive_call() -> Data { Data { x: 0, y: 0 } }
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! log_enabled {
+ (target: $target:expr, $lvl:expr) => ({
+ let lvl = $lvl;
+ lvl <= $crate::__static_max_level() && lvl <= $crate::max_log_level() &&
+ $crate::__enabled(lvl, $target)
+ });
+ ($lvl:expr) => (log_enabled!(target: module_path!(), $lvl))
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/log-0.3.8/tests/filters.rs
@@ -0,0 +1,76 @@
+#[macro_use] extern crate log;
+
+use std::sync::{Arc, Mutex};
+use log::{LogLevel, LogLevelFilter, Log, LogRecord, LogMetadata};
+use log::MaxLogLevelFilter;
+
+#[cfg(feature = "use_std")]
+use log::set_logger;
+#[cfg(not(feature = "use_std"))]
+fn set_logger<M>(make_logger: M) -> Result<(), log::SetLoggerError>
+ where M: FnOnce(MaxLogLevelFilter) -> Box<Log> {
+ unsafe {
+ log::set_logger_raw(|x| std::mem::transmute(make_logger(x)))
+ }
+}
+
+struct State {
+ last_log: Mutex<Option<LogLevel>>,
+ filter: MaxLogLevelFilter,
+}
+
+struct Logger(Arc<State>);
+
+impl Log for Logger {
+ fn enabled(&self, _: &LogMetadata) -> bool {
+ true
+ }
+
+ fn log(&self, record: &LogRecord) {
+ *self.0.last_log.lock().unwrap() = Some(record.level());
+ }
+}
+
+fn main() {
+ let mut a = None;
+ set_logger(|max| {
+ let me = Arc::new(State {
+ last_log: Mutex::new(None),
+ filter: max,
+ });
+ a = Some(me.clone());
+ Box::new(Logger(me))
+ }).unwrap();
+ let a = a.unwrap();
+
+ test(&a, LogLevelFilter::Off);
+ test(&a, LogLevelFilter::Error);
+ test(&a, LogLevelFilter::Warn);
+ test(&a, LogLevelFilter::Info);
+ test(&a, LogLevelFilter::Debug);
+ test(&a, LogLevelFilter::Trace);
+}
+
+fn test(a: &State, filter: LogLevelFilter) {
+ a.filter.set(filter);
+ error!("");
+ last(&a, t(LogLevel::Error, filter));
+ warn!("");
+ last(&a, t(LogLevel::Warn, filter));
+ info!("");
+ last(&a, t(LogLevel::Info, filter));
+ debug!("");
+ last(&a, t(LogLevel::Debug, filter));
+ trace!("");
+ last(&a, t(LogLevel::Trace, filter));
+
+ fn t(lvl: LogLevel, filter: LogLevelFilter) -> Option<LogLevel> {
+ if lvl <= filter {Some(lvl)} else {None}
+ }
+}
+
+fn last(state: &State, expected: Option<LogLevel>) {
+ let mut lvl = state.last_log.lock().unwrap();
+ assert_eq!(*lvl, expected);
+ *lvl = None;
+}
--- a/third_party/rust/log/.cargo-checksum.json
+++ b/third_party/rust/log/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".travis.yml":"985cf95c79f32c65766927fd6ef5079f8c14f235ddb4213e6410d90a86a95811","Cargo.toml":"0a4a756f7ef47f5dfa221a173b21f9ec496b448aafcd9bde08d9d16935b55007","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"aa8356455efcc3d49f66e7fa394eac292c9158164dff074e32c699b64891cb4b","appveyor.yml":"c61473b8c780ad2626282ce2b2ba0ef278082b6afe151a62ff419f33eaf90221","src/lib.rs":"75b44acfc9627b821cd725649db07693a43b2e44b2fac19b79354c6d950c4038","src/macros.rs":"3953610da3ee2dc393262b753f2406d1864a1cbd74d2bd20d279e09aabfe7131","tests/filters.rs":"cc61ed41a6cd77e5aef91cc8c76216b492d8de34f00635254f3835a3d964ce22"},"package":"880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"}
\ No newline at end of file
+{"files":{".travis.yml":"8e95f3543ff36e1fd0e2e2fcc98b31e20dcc19d220f3d7d19bfb9aeb61030823","CHANGELOG.md":"cdfe104547fca9d80b95cff2c6ef5af7cdcd0a17886ec3722c157a598abec018","Cargo.toml":"ba13b382a64b910241ce4fc2ac4f45dd3a8f404f762f07958004a41de1cb55df","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"95873097578066ef6a0cc395f1aad5596762570ba1476757643fb319e3892481","appveyor.yml":"d5376a881aef6dc3bed6a6b51f1f1c3801b88fc77a12895f6953190256e965bc","src/lib.rs":"4ffa677655636a6c111026d318c92bb53bd91988e601fcdcdbe1f43b1997b8fd","src/macros.rs":"064c96e154b58b61b8a4f11cab9c0664dd171010f578af438fad0dc1d796ac5c","src/serde.rs":"7617ffa21dde363a06389f8e26661f35550c1a01ff142f81275e95f42b79c854","tests/filters.rs":"6aee024d4594b4fde772e35c5d3318e5aa5d9aa4eaeafb04e4c7c922be4ac837"},"package":"89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"}
\ No newline at end of file
--- a/third_party/rust/log/.travis.yml
+++ b/third_party/rust/log/.travis.yml
@@ -1,29 +1,20 @@
language: rust
sudo: false
rust:
+ - 1.16.0
- stable
- beta
- nightly
-before_script:
- - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
script:
- cargo build --verbose
- - ([ $TRAVIS_RUST_VERSION != nightly ] || cargo build --verbose --no-default-features)
- - ([ $TRAVIS_RUST_VERSION != nightly ] || cargo build --verbose --features nightly)
+ - cargo build --verbose --features serde
+ - cargo build --verbose --features std
- cargo test --verbose
- - ([ $TRAVIS_RUST_VERSION != nightly ] || cargo test --verbose --no-default-features)
- - cargo test --verbose --manifest-path env/Cargo.toml
- - cargo test --verbose --manifest-path env/Cargo.toml --no-default-features
+ - cargo test --verbose --features serde
+ - cargo test --verbose --features std
- cargo run --verbose --manifest-path tests/max_level_features/Cargo.toml
- cargo run --verbose --manifest-path tests/max_level_features/Cargo.toml --release
- - ([ $TRAVIS_RUST_VERSION != nightly ] || cargo doc --no-deps --features nightly)
- - CARGO_TARGET_DIR=target cargo doc --no-deps --manifest-path env/Cargo.toml
-after_success:
- - travis-cargo --only nightly doc-upload
-env:
- global:
- secure: "VPHgnszydMudYTY8cthHj/Dmxqp7OmTiu4Sa/705Udsx+tYblTv+8WdThkClo3C/asStVcxlaRWAp91UX32/k4SfkPz17XId3Wadyt03r73ANm6ZOWY+qty+3/LINm54kuTxYUDDTbD6NaFNPFQLIE0xCpJeiXUQTlaMk6z0W3M="
notifications:
email:
on_success: never
new file mode 100644
--- /dev/null
+++ b/third_party/rust/log/CHANGELOG.md
@@ -0,0 +1,83 @@
+# Change Log
+
+## [Unreleased]
+
+## [0.4.1] - 2017-12-30
+
+### Fixed
+
+* Some doc links were fixed.
+
+## [0.4.0] - 2017-12-24
+
+The changes in this release include cleanup of some obscure functionality and a more robust public
+API designed to support bridges to other logging systems, and provide more flexibility to new
+features in the future.
+
+### Compatibility
+
+Vast portions of the Rust ecosystem use the 0.3.x release series of log, and we don't want to force
+the community to go through the pain of upgrading every crate to 0.4.x at the exact same time. Along
+with 0.4.0, we've published a new 0.3.9 release which acts as a "shim" over 0.4.0. This will allow
+crates using either version to coexist without losing messages from one side or the other.
+
+There is one caveat - a log message generated by a crate using 0.4.x but consumed by a logging
+implementation using 0.3.x will not have a file name or module path. Applications affected by this
+can upgrade their logging implementations to one using 0.4.x to avoid losing this information. The
+other direction does not lose any information, fortunately!
+
+**TL;DR** Libraries should feel comfortable upgrading to 0.4.0 without treating that as a breaking
+change. Applications may need to update their logging implementation (e.g. env-logger) to a newer
+version using log 0.4.x to avoid losing module and file information.
+
+### New
+
+* The crate is now `no_std` by default.
+* `Level` and `LevelFilter` now implement `Serialize` and `Deserialize` when the `serde` feature is
+ enabled.
+* The `Record` and `Metadata` types can now be constructed by third-party code via a builder API.
+* The `logger` free function returns a reference to the logger implementation. This, along with the
+ ability to construct `Record`s, makes it possible to bridge from another logging framework to
+ this one without digging into the private internals of the crate. The standard `error!` `warn!`,
+ etc, macros now exclusively use the public API of the crate rather than "secret" internal APIs.
+* `Log::flush` has been added to allow crates to tell the logging implementation to ensure that all
+ "in flight" log events have been persisted. This can be used, for example, just before an
+ application exits to ensure that asynchronous log sinks finish their work.
+
+### Removed
+
+* The `shutdown` and `shutdown_raw` functions have been removed. Supporting shutdown significantly
+ complicated the implementation and imposed a performance cost on each logging operation.
+* The `log_panics` function and its associated `nightly` Cargo feature have been removed. Use the
+ [log-panics](https://crates.io/crates/log-panics) instead.
+
+### Changed
+
+* The `Log` prefix has been removed from type names. For example, `LogLevelFilter` is now
+ `LevelFilter`, and `LogRecord` is now `Record`.
+* The `MaxLogLevelFilter` object has been removed in favor of a `set_max_level` free function.
+* The `set_logger` free functions have been restructured. The logger is now directly passed to the
+ functions rather than a closure which returns the logger. `set_logger` now takes a `&'static
+ Log` and is usable in `no_std` contexts in place of the old `set_logger_raw`. `set_boxed_logger`
+ is a convenience function which takes a `Box<Log>` but otherwise acts like `set_logger`. It
+ requires the `std` feature.
+* The `file` and `module_path` values in `Record` no longer have the `'static` lifetime to support
+ integration with other logging frameworks that don't provide a `'static` lifetime for the
+ equivalent values.
+* The `file`, `line`, and `module_path` values in `Record` are now `Option`s to support integration
+ with other logging frameworks that don't provide those values.
+
+### In the Future
+
+* We're looking to add support for *structured* logging - the inclusion of extra key-value pairs of
+ information in a log event in addition to the normal string message. This should be able to be
+ added in a backwards compatible manner to the 0.4.x series when the design is worked out.
+
+## Older
+
+Look at the [release tags] for information about older releases.
+
+[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.1...HEAD
+[0.4.1]: https://github.com/rust-lang-nursery/log/compare/0.4.0...0.4.1
+[0.4.0]: https://github.com/rust-lang-nursery/log/compare/0.3.8...0.4.0
+[release tags]: https://github.com/rust-lang-nursery/log/releases
--- a/third_party/rust/log/Cargo.toml
+++ b/third_party/rust/log/Cargo.toml
@@ -7,43 +7,53 @@
#
# 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 = "log"
-version = "0.3.8"
+version = "0.4.1"
authors = ["The Rust Project Developers"]
description = "A lightweight logging facade for Rust\n"
homepage = "https://github.com/rust-lang/log"
documentation = "https://docs.rs/log"
readme = "README.md"
+keywords = ["logging"]
categories = ["development-tools::debugging"]
license = "MIT/Apache-2.0"
repository = "https://github.com/rust-lang/log"
+[package.metadata.docs.rs]
+features = ["std", "serde"]
[[test]]
name = "filters"
harness = false
+[dependencies.cfg-if]
+version = "0.1.2"
+
+[dependencies.serde]
+version = "1.0"
+optional = true
+default-features = false
+[dev-dependencies.serde_test]
+version = "1.0"
[features]
+max_level_debug = []
+max_level_error = []
max_level_info = []
-nightly = []
+max_level_off = []
+max_level_trace = []
max_level_warn = []
release_max_level_debug = []
+release_max_level_error = []
release_max_level_info = []
release_max_level_off = []
-release_max_level_error = []
-max_level_debug = []
+release_max_level_trace = []
release_max_level_warn = []
-use_std = []
-max_level_off = []
-max_level_trace = []
-release_max_level_trace = []
-max_level_error = []
-default = ["use_std"]
+std = []
[badges.appveyor]
repository = "alexcrichton/log"
[badges.travis-ci]
repository = "rust-lang-nursery/log"
--- a/third_party/rust/log/README.md
+++ b/third_party/rust/log/README.md
@@ -1,34 +1,33 @@
log
===
A Rust library providing a lightweight logging *facade*.
[![Build Status](https://travis-ci.org/rust-lang-nursery/log.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/log)
[![Build status](https://ci.appveyor.com/api/projects/status/nopdjmmjt45xcrki?svg=true)](https://ci.appveyor.com/project/alexcrichton/log)
-* [`log` documentation](https://doc.rust-lang.org/log)
-* [`env_logger` documentation](https://doc.rust-lang.org/log/env_logger)
+* [`log` documentation](https://docs.rs/log)
A logging facade provides a single logging API that abstracts over the actual
logging implementation. Libraries can use the logging API provided by this
crate, and the consumer of those libraries can choose the logging
implementation that is most suitable for its use case.
## Usage
## In libraries
Libraries should link only to the `log` crate, and use the provided macros to
log whatever information will be useful to downstream consumers:
```toml
[dependencies]
-log = "0.3"
+log = "0.4"
```
```rust
#[macro_use]
extern crate log;
pub fn shave_the_yak(yak: &Yak) {
trace!("Commencing yak shaving");
@@ -45,133 +44,31 @@ pub fn shave_the_yak(yak: &Yak) {
}
}
}
}
```
## In executables
+In order to produce log output executables have to use a logger implementation compatible with the facade.
+There are many available implementations to chose from, here are some of the most popular ones:
+
+* Simple minimal loggers:
+ * [`env_logger`](https://docs.rs/env_logger/*/env_logger/)
+ * [`simple_logger`](https://github.com/borntyping/rust-simple_logger)
+ * [`simplelog`](https://github.com/drakulix/simplelog.rs)
+ * [`pretty_env_logger`](https://docs.rs/pretty_env_logger/*/pretty_env_logger/)
+ * [`stderrlog`](https://docs.rs/stderrlog/*/stderrlog/)
+ * [`flexi_logger`](https://docs.rs/flexi_logger/*/flexi_logger/)
+* Complex configurable frameworks:
+ * [`log4rs`](https://docs.rs/log4rs/*/log4rs/)
+ * [`fern`](https://docs.rs/fern/*/fern/)
+* Adaptors for other facilities:
+ * [`syslog`](https://docs.rs/syslog/*/syslog/)
+ * [`slog-stdlog`](https://docs.rs/slog-stdlog/*/slog_stdlog/)
+
Executables should choose a logger implementation and initialize it early in the
runtime of the program. Logger implementations will typically include a
function to do this. Any log messages generated before the logger is
initialized will be ignored.
The executable itself may use the `log` crate to log as well.
-
-The `env_logger` crate provides a logger implementation that mirrors the
-functionality of the old revision of the `log` crate.
-
-```toml
-[dependencies]
-log = "0.3"
-env_logger = "0.3"
-```
-
-```rust
-#[macro_use]
-extern crate log;
-extern crate env_logger;
-
-fn main() {
- env_logger::init().unwrap();
-
- info!("starting up");
-
- // ...
-}
-```
-
-## In tests
-
-Tests can use the `env_logger` crate to see log messages generated during that test:
-
-```toml
-[dependencies]
-log = "0.3"
-
-[dev-dependencies]
-env_logger = "0.3"
-```
-
-```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::*;
- extern crate env_logger;
-
- #[test]
- fn it_adds_one() {
- let _ = env_logger::init();
- info!("can log from the test too");
- assert_eq!(3, add_one(2));
- }
-
- #[test]
- fn it_handles_negative_numbers() {
- let _ = env_logger::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::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 `LogBuilder` to change the log target:
-
-```rust
-use std::env;
-use env_logger::{LogBuilder, LogTarget};
-
-let mut builder = LogBuilder::new();
-builder.target(LogTarget::Stdout);
-if env::var("RUST_LOG").is_ok() {
- builder.parse(&env::var("RUST_LOG").unwrap());
-}
-builder.init().unwrap();
-```
--- a/third_party/rust/log/appveyor.yml
+++ b/third_party/rust/log/appveyor.yml
@@ -10,9 +10,10 @@ install:
- SET PATH=%PATH%;C:\MinGW\bin
- rustc -V
- cargo -V
build: false
test_script:
- cargo test --verbose
- - cargo test --manifest-path env/Cargo.toml
+ - cargo test --verbose --features serde
+ - cargo test --verbose --features std
--- a/third_party/rust/log/src/lib.rs
+++ b/third_party/rust/log/src/lib.rs
@@ -8,29 +8,43 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A lightweight logging facade.
//!
//! The `log` crate provides a single logging API that abstracts over the
//! actual logging implementation. Libraries can use the logging API provided
//! by this crate, and the consumer of those libraries can choose the logging
-//! framework that is most suitable for its use case.
+//! implementation that is most suitable for its use case.
//!
//! If no logging implementation is selected, the facade falls back to a "noop"
//! implementation that ignores all log messages. The overhead in this case
//! is very small - just an integer load, comparison and jump.
//!
//! A log request consists of a _target_, a _level_, and a _body_. A target is a
//! string which defaults to the module path of the location of the log request,
//! though that default may be overridden. Logger implementations typically use
//! the target to filter requests based on some user configuration.
//!
//! # Use
//!
+//! The basic use of the log crate is through the five logging macros: [`error!`],
+//! [`warn!`], [`info!`], [`debug!`] and [`trace!`]
+//! where `error!` represents the highest-priority log level, and `trace!` the lowest.
+//!
+//! Each of these macros accept format strings similarly to [`println!`].
+//!
+//!
+//! [`error!`]: ./macro.error.html
+//! [`warn!`]: ./macro.warn.html
+//! [`info!`]: ./macro.info.html
+//! [`debug!`]: ./macro.debug.html
+//! [`trace!`]: ./macro.trace.html
+//! [`println!`]: https://doc.rust-lang.org/stable/std/macro.println.html
+//!
//! ## In libraries
//!
//! Libraries should link only to the `log` crate, and use the provided
//! macros to log whatever information will be useful to downstream consumers.
//!
//! ### Examples
//!
//! ```rust
@@ -57,223 +71,252 @@
//! }
//! }
//! }
//! # fn main() {}
//! ```
//!
//! ## In executables
//!
-//! Executables should choose a logging framework and initialize it early in the
-//! runtime of the program. Logging frameworks will typically include a
-//! function to do this. Any log messages generated before the framework is
-//! initialized will be ignored.
+//! Executables should choose a logging implementation and initialize it early in the
+//! runtime of the program. Logging implementations will typically include a
+//! function to do this. Any log messages generated before
+//! the implementation is initialized will be ignored.
//!
//! The executable itself may use the `log` crate to log as well.
//!
//! ### Warning
//!
//! The logging system may only be initialized once.
//!
-//! ### Examples
+//! # Available logging implementations
//!
-//! ```rust,ignore
-//! #[macro_use]
-//! extern crate log;
-//! extern crate env_logger;
+//! In order to produce log output executables have to use
+//! a logger implementation compatible with the facade.
+//! There are many available implementations to choose from,
+//! here are some of the most popular ones:
//!
-//! fn main() {
-//! // Select env_logger, one possible logger implementation
-//! // (see https://doc.rust-lang.org/log/env_logger/index.html)
-//! env_logger::init().unwrap();
-//!
-//! info!("starting up");
-//! error!("error: {}", 404);
-//!
-//! // ...
-//! }
-//! ```
+//! * Simple minimal loggers:
+//! * [env_logger]
+//! * [simple_logger]
+//! * [simplelog]
+//! * [pretty_env_logger]
+//! * [stderrlog]
+//! * [flexi_logger]
+//! * Complex configurable frameworks:
+//! * [log4rs]
+//! * [fern]
+//! * Adaptors for other facilities:
+//! * [syslog]
+//! * [slog-stdlog]
//!
-//! # Logger implementations
+//! # Implementing a Logger
//!
//! Loggers implement the [`Log`] trait. Here's a very basic example that simply
//! logs all messages at the [`Error`][level_link], [`Warn`][level_link] or
//! [`Info`][level_link] levels to stdout:
//!
//! ```rust
//! extern crate log;
//!
-//! use log::{LogRecord, LogLevel, LogMetadata};
+//! use log::{Record, Level, Metadata};
//!
//! struct SimpleLogger;
//!
//! impl log::Log for SimpleLogger {
-//! fn enabled(&self, metadata: &LogMetadata) -> bool {
-//! metadata.level() <= LogLevel::Info
+//! fn enabled(&self, metadata: &Metadata) -> bool {
+//! metadata.level() <= Level::Info
//! }
//!
-//! fn log(&self, record: &LogRecord) {
+//! fn log(&self, record: &Record) {
//! if self.enabled(record.metadata()) {
//! println!("{} - {}", record.level(), record.args());
//! }
//! }
+//!
+//! fn flush(&self) {}
//! }
//!
//! # fn main() {}
//! ```
//!
//! Loggers are installed by calling the [`set_logger`] function. It takes a
-//! closure which is provided a [`MaxLogLevelFilter`] token and returns a
-//! [`Log`] trait object. The [`MaxLogLevelFilter`] token controls the global
+//! closure which is provided a [`MaxLevelFilter`] token and returns a
+//! [`Log`] trait object. The [`MaxLevelFilter`] token controls the global
//! maximum log level. The logging facade uses this as an optimization to
//! improve performance of log messages at levels that are disabled. In the
//! case of our example logger, we'll want to set the maximum log level to
//! [`Info`][level_link], since we ignore any [`Debug`][level_link] or
-//! [`Trace`][level_link] level log messages. A logging framework should
-//! provide a function that wraps a call to [`set_logger`], handling
+//! [`Trace`][level_link] level log messages. A logging implementation
+//! should provide a function that wraps a call to [`set_logger`], handling
//! initialization of the logger:
//!
//! ```rust
//! # extern crate log;
-//! # use log::{LogLevel, LogLevelFilter, SetLoggerError, LogMetadata};
+//! # use log::{Level, Metadata};
//! # struct SimpleLogger;
//! # impl log::Log for SimpleLogger {
-//! # fn enabled(&self, _: &LogMetadata) -> bool { false }
-//! # fn log(&self, _: &log::LogRecord) {}
+//! # fn enabled(&self, _: &Metadata) -> bool { false }
+//! # fn log(&self, _: &log::Record) {}
+//! # fn flush(&self) {}
//! # }
//! # fn main() {}
-//! # #[cfg(feature = "use_std")]
+//! use log::{SetLoggerError, LevelFilter};
+//!
+//! static LOGGER: SimpleLogger = SimpleLogger;
+//!
//! pub fn init() -> Result<(), SetLoggerError> {
-//! log::set_logger(|max_log_level| {
-//! max_log_level.set(LogLevelFilter::Info);
-//! Box::new(SimpleLogger)
-//! })
+//! log::set_logger(&LOGGER)
//! }
//! ```
//!
-//! # Use with `no_std`
+//! # Use with `std`
//!
-//! To use the `log` crate without depending on `libstd`, you need to specify
-//! `default-features = false` when specifying the dependency in `Cargo.toml`.
-//! This makes no difference to libraries using `log` since the logging API
-//! remains the same. However executables will need to use the [`set_logger_raw`]
-//! function to initialize a logger and the [`shutdown_logger_raw`] function to
-//! shut down the global logger before exiting:
+//! `set_logger` requires you to provide a `&'static Log`, which can be hard if
+//! your logger depends on some runtime configuration. The `set_boxed_logger`
+//! function is available with the `std` Cargo feature. It is identical to
+//! `set_logger` except that it requires you to provide a `Box<Log>` rather than
+//! a `&'static Log`:
//!
//! ```rust
//! # extern crate log;
-//! # use log::{LogLevel, LogLevelFilter, SetLoggerError, ShutdownLoggerError,
-//! # LogMetadata};
+//! # use log::{Level, LevelFilter, Log, SetLoggerError, Metadata};
//! # struct SimpleLogger;
//! # impl log::Log for SimpleLogger {
-//! # fn enabled(&self, _: &LogMetadata) -> bool { false }
-//! # fn log(&self, _: &log::LogRecord) {}
-//! # }
-//! # impl SimpleLogger {
+//! # fn enabled(&self, _: &Metadata) -> bool { false }
+//! # fn log(&self, _: &log::Record) {}
//! # fn flush(&self) {}
//! # }
//! # fn main() {}
+//! # #[cfg(feature = "std")]
//! pub fn init() -> Result<(), SetLoggerError> {
-//! unsafe {
-//! log::set_logger_raw(|max_log_level| {
-//! static LOGGER: SimpleLogger = SimpleLogger;
-//! max_log_level.set(LogLevelFilter::Info);
-//! &SimpleLogger
-//! })
-//! }
-//! }
-//! pub fn shutdown() -> Result<(), ShutdownLoggerError> {
-//! log::shutdown_logger_raw().map(|logger| {
-//! let logger = unsafe { &*(logger as *const SimpleLogger) };
-//! logger.flush();
-//! })
+//! log::set_boxed_logger(Box::new(SimpleLogger))
//! }
//! ```
//!
+//! # Compile time filters
+//!
+//! Log levels can be statically disabled at compile time via Cargo features. Log invocations at
+//! disabled levels will be skipped and will not even be present in the resulting binary unless the
+//! log level is specified dynamically. This level is configured separately for release and debug
+//! builds. The features are:
+//!
+//! * `max_level_off`
+//! * `max_level_error`
+//! * `max_level_warn`
+//! * `max_level_info`
+//! * `max_level_debug`
+//! * `max_level_trace`
+//! * `release_max_level_off`
+//! * `release_max_level_error`
+//! * `release_max_level_warn`
+//! * `release_max_level_info`
+//! * `release_max_level_debug`
+//! * `release_max_level_trace`
+//!
+//! These features control the value of the `STATIC_MAX_LEVEL` constant. The logging macros check
+//! this value before logging a message. By default, no levels are disabled.
+//!
+//! For example, a crate can disable trace level logs in debug builds and trace, info, and warn
+//! level logs in release builds with the following configuration:
+//!
+//! ```toml
+//! [dependencies]
+//! log = { version = "0.4", features = ["max_level_debug", "release_max_level_warn"] }
+//! ```
+//!
+//! # Version compatibility
+//!
+//! The 0.3 and 0.4 versions of the `log` crate are almost entirely compatible. Log messages
+//! made using `log` 0.3 will forward transparently to a logger implementation using `log` 0.4. Log
+//! messages made using `log` 0.4 will forward to a logger implementation using `log` 0.3, but the
+//! module path and file name information associated with the message will unfortunately be lost.
+//!
//! [`Log`]: trait.Log.html
-//! [level_link]: enum.LogLevel.html
+//! [level_link]: enum.Level.html
//! [`set_logger`]: fn.set_logger.html
-//! [`MaxLogLevelFilter`]: struct.MaxLogLevelFilter.html
-//! [`set_logger_raw`]: fn.set_logger_raw.html
+//! [`MaxLevelFilter`]: struct.MaxLevelFilter.html
+//! [`try_set_logger_raw`]: fn.try_set_logger_raw.html
//! [`shutdown_logger_raw`]: fn.shutdown_logger_raw.html
+//! [env_logger]: https://docs.rs/env_logger/*/env_logger/
+//! [simple_logger]: https://github.com/borntyping/rust-simple_logger
+//! [simplelog]: https://github.com/drakulix/simplelog.rs
+//! [pretty_env_logger]: https://docs.rs/pretty_env_logger/*/pretty_env_logger/
+//! [stderrlog]: https://docs.rs/stderrlog/*/stderrlog/
+//! [flexi_logger]: https://docs.rs/flexi_logger/*/flexi_logger/
+//! [syslog]: https://docs.rs/syslog/*/syslog/
+//! [slog-stdlog]: https://docs.rs/slog-stdlog/*/slog_stdlog/
+//! [log4rs]: https://docs.rs/log4rs/*/log4rs/
+//! [fern]: https://docs.rs/fern/*/fern/
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
- html_root_url = "https://doc.rust-lang.org/log/")]
+ html_root_url = "https://docs.rs/log/0.4.1")]
#![warn(missing_docs)]
#![deny(missing_debug_implementations)]
-#![cfg_attr(feature = "nightly", feature(panic_handler))]
-#![cfg_attr(not(feature = "use_std"), no_std)]
+#![cfg_attr(not(feature = "std"), no_std)]
// 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"))]
-#[cfg(not(feature = "use_std"))]
+#[cfg(not(feature = "std"))]
extern crate core as std;
+#[macro_use]
+extern crate cfg_if;
+
use std::cmp;
-#[cfg(feature = "use_std")]
+#[cfg(feature = "std")]
use std::error;
use std::fmt;
use std::mem;
-use std::ops::Deref;
use std::str::FromStr;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+
#[macro_use]
mod macros;
+mod serde;
-// The setup here is a bit weird to make shutdown_logger_raw work.
-//
-// There are four different states that we care about: the logger's
-// uninitialized, the logger's initializing (set_logger's been called but
-// LOGGER hasn't actually been set yet), the logger's active, or the logger is
-// shut down after calling shutdown_logger_raw.
-//
// The LOGGER static holds a pointer to the global logger. It is protected by
// the STATE static which determines whether LOGGER has been initialized yet.
-//
-// The shutdown_logger_raw routine needs to make sure that no threads are
-// actively logging before it returns. The number of actively logging threads is
-// tracked in the REFCOUNT static. The routine first sets STATE back to
-// INITIALIZING. All logging calls past that point will immediately return
-// without accessing the logger. At that point, the at_exit routine just waits
-// for the refcount to reach 0 before deallocating the logger. Note that the
-// refcount does not necessarily monotonically decrease at this point, as new
-// log calls still increment and decrement it, but the interval in between is
-// small enough that the wait is really just for the active log calls to finish.
+static mut LOGGER: &'static Log = &NopLogger;
+static STATE: AtomicUsize = ATOMIC_USIZE_INIT;
-static mut LOGGER: *const Log = &NopLogger;
-static STATE: AtomicUsize = ATOMIC_USIZE_INIT;
-static REFCOUNT: AtomicUsize = ATOMIC_USIZE_INIT;
-
+// There are three different states that we care about: the logger's
+// uninitialized, the logger's initializing (set_logger's been called but
+// LOGGER hasn't actually been set yet), or the logger's active.
const UNINITIALIZED: usize = 0;
const INITIALIZING: usize = 1;
const INITIALIZED: usize = 2;
static MAX_LOG_LEVEL_FILTER: AtomicUsize = ATOMIC_USIZE_INIT;
-static LOG_LEVEL_NAMES: [&'static str; 6] = ["OFF", "ERROR", "WARN", "INFO",
- "DEBUG", "TRACE"];
+static LOG_LEVEL_NAMES: [&'static str; 6] = ["OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"];
-/// An enum representing the available verbosity levels of the logging framework.
+static SET_LOGGER_ERROR: &'static str = "attempted to set a logger after the logging system was \
+ already initialized";
+static LEVEL_PARSE_ERROR: &'static str = "attempted to convert a string that doesn't match an \
+ existing log level";
+
+/// An enum representing the available verbosity levels of the logger.
///
-/// Typical usage includes: checking if a certain `LogLevel` is enabled with
-/// [`log_enabled!`](macro.log_enabled.html), specifying the `LogLevel` of
-/// [`log!`](macro.log.html), and comparing a `LogLevel` directly to a
-/// [`LogLevelFilter`](enum.LogLevelFilter.html).
+/// Typical usage includes: checking if a certain `Level` is enabled with
+/// [`log_enabled!`](macro.log_enabled.html), specifying the `Level` of
+/// [`log!`](macro.log.html), and comparing a `Level` directly to a
+/// [`LevelFilter`](enum.LevelFilter.html).
#[repr(usize)]
#[derive(Copy, Eq, Debug, Hash)]
-pub enum LogLevel {
+pub enum Level {
/// The "error" level.
///
/// Designates very serious errors.
- Error = 1, // This way these line up with the discriminants for LogLevelFilter below
+ Error = 1, // This way these line up with the discriminants for LevelFilter below
/// The "warn" level.
///
/// Designates hazardous situations.
Warn,
/// The "info" level.
///
/// Designates useful information.
Info,
@@ -282,54 +325,54 @@ pub enum LogLevel {
/// Designates lower priority information.
Debug,
/// The "trace" level.
///
/// Designates very low priority, often extremely verbose, information.
Trace,
}
-impl Clone for LogLevel {
+impl Clone for Level {
#[inline]
- fn clone(&self) -> LogLevel {
+ fn clone(&self) -> Level {
*self
}
}
-impl PartialEq for LogLevel {
+impl PartialEq for Level {
#[inline]
- fn eq(&self, other: &LogLevel) -> bool {
+ fn eq(&self, other: &Level) -> bool {
*self as usize == *other as usize
}
}
-impl PartialEq<LogLevelFilter> for LogLevel {
+impl PartialEq<LevelFilter> for Level {
#[inline]
- fn eq(&self, other: &LogLevelFilter) -> bool {
+ fn eq(&self, other: &LevelFilter) -> bool {
*self as usize == *other as usize
}
}
-impl PartialOrd for LogLevel {
+impl PartialOrd for Level {
#[inline]
- fn partial_cmp(&self, other: &LogLevel) -> Option<cmp::Ordering> {
+ fn partial_cmp(&self, other: &Level) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
-impl PartialOrd<LogLevelFilter> for LogLevel {
+impl PartialOrd<LevelFilter> for Level {
#[inline]
- fn partial_cmp(&self, other: &LogLevelFilter) -> Option<cmp::Ordering> {
+ fn partial_cmp(&self, other: &LevelFilter) -> Option<cmp::Ordering> {
Some((*self as usize).cmp(&(*other as usize)))
}
}
-impl Ord for LogLevel {
+impl Ord for Level {
#[inline]
- fn cmp(&self, other: &LogLevel) -> cmp::Ordering {
+ fn cmp(&self, other: &Level) -> cmp::Ordering {
(*self as usize).cmp(&(*other as usize))
}
}
fn ok_or<T, E>(t: Option<T>, e: E) -> Result<T, E> {
match t {
Some(t) => Ok(t),
None => Err(e),
@@ -342,699 +385,955 @@ fn eq_ignore_ascii_case(a: &str, b: &str
if c >= b'a' && c <= b'z' {
c - b'a' + b'A'
} else {
c
}
}
if a.len() == b.len() {
- a.bytes()
- .zip(b.bytes())
- .all(|(a, b)| to_ascii_uppercase(a) == to_ascii_uppercase(b))
+ a.bytes().zip(b.bytes()).all(|(a, b)| {
+ to_ascii_uppercase(a) == to_ascii_uppercase(b)
+ })
} else {
false
}
}
-impl FromStr for LogLevel {
- type Err = ();
- fn from_str(level: &str) -> Result<LogLevel, ()> {
- ok_or(LOG_LEVEL_NAMES.iter()
- .position(|&name| eq_ignore_ascii_case(name, level))
- .into_iter()
- .filter(|&idx| idx != 0)
- .map(|idx| LogLevel::from_usize(idx).unwrap())
- .next(), ())
+impl FromStr for Level {
+ type Err = ParseLevelError;
+ fn from_str(level: &str) -> Result<Level, Self::Err> {
+ ok_or(
+ LOG_LEVEL_NAMES
+ .iter()
+ .position(|&name| eq_ignore_ascii_case(name, level))
+ .into_iter()
+ .filter(|&idx| idx != 0)
+ .map(|idx| Level::from_usize(idx).unwrap())
+ .next(),
+ ParseLevelError(()),
+ )
}
}
-impl fmt::Display for LogLevel {
+impl fmt::Display for Level {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.pad(LOG_LEVEL_NAMES[*self as usize])
}
}
-impl LogLevel {
- fn from_usize(u: usize) -> Option<LogLevel> {
+impl Level {
+ fn from_usize(u: usize) -> Option<Level> {
match u {
- 1 => Some(LogLevel::Error),
- 2 => Some(LogLevel::Warn),
- 3 => Some(LogLevel::Info),
- 4 => Some(LogLevel::Debug),
- 5 => Some(LogLevel::Trace),
- _ => None
+ 1 => Some(Level::Error),
+ 2 => Some(Level::Warn),
+ 3 => Some(Level::Info),
+ 4 => Some(Level::Debug),
+ 5 => Some(Level::Trace),
+ _ => None,
}
}
/// Returns the most verbose logging level.
#[inline]
- pub fn max() -> LogLevel {
- LogLevel::Trace
+ pub fn max() -> Level {
+ Level::Trace
}
- /// Converts the `LogLevel` to the equivalent `LogLevelFilter`.
+ /// Converts the `Level` to the equivalent `LevelFilter`.
#[inline]
- pub fn to_log_level_filter(&self) -> LogLevelFilter {
- LogLevelFilter::from_usize(*self as usize).unwrap()
+ pub fn to_level_filter(&self) -> LevelFilter {
+ LevelFilter::from_usize(*self as usize).unwrap()
}
}
-/// An enum representing the available verbosity level filters of the logging
-/// framework.
+/// An enum representing the available verbosity level filters of the logger.
///
-/// A `LogLevelFilter` may be compared directly to a [`LogLevel`](enum.LogLevel.html).
-/// Use this type to [`get()`](struct.MaxLogLevelFilter.html#method.get) and
-/// [`set()`](struct.MaxLogLevelFilter.html#method.set) the
-/// [`MaxLogLevelFilter`](struct.MaxLogLevelFilter.html), or to match with the getter
-/// [`max_log_level()`](fn.max_log_level.html).
+/// A `LevelFilter` may be compared directly to a [`Level`]. Use this type
+/// to get and set the maximum log level with [`max_level()`] and [`set_max_level`].
+///
+/// [`Level`]: enum.Level.html
+/// [`max_level()`]: fn.max_level.html
+/// [`set_max_level`]: fn.set_max_level.html
#[repr(usize)]
#[derive(Copy, Eq, Debug, Hash)]
-pub enum LogLevelFilter {
+pub enum LevelFilter {
/// A level lower than all log levels.
Off,
/// Corresponds to the `Error` log level.
Error,
/// Corresponds to the `Warn` log level.
Warn,
/// Corresponds to the `Info` log level.
Info,
/// Corresponds to the `Debug` log level.
Debug,
/// Corresponds to the `Trace` log level.
Trace,
}
// Deriving generates terrible impls of these traits
-impl Clone for LogLevelFilter {
+impl Clone for LevelFilter {
#[inline]
- fn clone(&self) -> LogLevelFilter {
+ fn clone(&self) -> LevelFilter {
*self
}
}
-impl PartialEq for LogLevelFilter {
+impl PartialEq for LevelFilter {
#[inline]
- fn eq(&self, other: &LogLevelFilter) -> bool {
+ fn eq(&self, other: &LevelFilter) -> bool {
*self as usize == *other as usize
}
}
-impl PartialEq<LogLevel> for LogLevelFilter {
+impl PartialEq<Level> for LevelFilter {
#[inline]
- fn eq(&self, other: &LogLevel) -> bool {
+ fn eq(&self, other: &Level) -> bool {
other.eq(self)
}
}
-impl PartialOrd for LogLevelFilter {
+impl PartialOrd for LevelFilter {
#[inline]
- fn partial_cmp(&self, other: &LogLevelFilter) -> Option<cmp::Ordering> {
+ fn partial_cmp(&self, other: &LevelFilter) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
-impl PartialOrd<LogLevel> for LogLevelFilter {
+impl PartialOrd<Level> for LevelFilter {
#[inline]
- fn partial_cmp(&self, other: &LogLevel) -> Option<cmp::Ordering> {
+ fn partial_cmp(&self, other: &Level) -> Option<cmp::Ordering> {
other.partial_cmp(self).map(|x| x.reverse())
}
}
-impl Ord for LogLevelFilter {
+impl Ord for LevelFilter {
#[inline]
- fn cmp(&self, other: &LogLevelFilter) -> cmp::Ordering {
+ fn cmp(&self, other: &LevelFilter) -> cmp::Ordering {
(*self as usize).cmp(&(*other as usize))
}
}
-impl FromStr for LogLevelFilter {
- type Err = ();
- fn from_str(level: &str) -> Result<LogLevelFilter, ()> {
- ok_or(LOG_LEVEL_NAMES.iter()
- .position(|&name| eq_ignore_ascii_case(name, level))
- .map(|p| LogLevelFilter::from_usize(p).unwrap()), ())
+impl FromStr for LevelFilter {
+ type Err = ParseLevelError;
+ fn from_str(level: &str) -> Result<LevelFilter, Self::Err> {
+ ok_or(
+ LOG_LEVEL_NAMES
+ .iter()
+ .position(|&name| eq_ignore_ascii_case(name, level))
+ .map(|p| LevelFilter::from_usize(p).unwrap()),
+ ParseLevelError(()),
+ )
}
}
-impl fmt::Display for LogLevelFilter {
+impl fmt::Display for LevelFilter {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", LOG_LEVEL_NAMES[*self as usize])
}
}
-impl LogLevelFilter {
- fn from_usize(u: usize) -> Option<LogLevelFilter> {
+impl LevelFilter {
+ fn from_usize(u: usize) -> Option<LevelFilter> {
match u {
- 0 => Some(LogLevelFilter::Off),
- 1 => Some(LogLevelFilter::Error),
- 2 => Some(LogLevelFilter::Warn),
- 3 => Some(LogLevelFilter::Info),
- 4 => Some(LogLevelFilter::Debug),
- 5 => Some(LogLevelFilter::Trace),
- _ => None
+ 0 => Some(LevelFilter::Off),
+ 1 => Some(LevelFilter::Error),
+ 2 => Some(LevelFilter::Warn),
+ 3 => Some(LevelFilter::Info),
+ 4 => Some(LevelFilter::Debug),
+ 5 => Some(LevelFilter::Trace),
+ _ => None,
}
}
/// Returns the most verbose logging level filter.
#[inline]
- pub fn max() -> LogLevelFilter {
- LogLevelFilter::Trace
+ pub fn max() -> LevelFilter {
+ LevelFilter::Trace
}
- /// Converts `self` to the equivalent `LogLevel`.
+ /// Converts `self` to the equivalent `Level`.
///
- /// Returns `None` if `self` is `LogLevelFilter::Off`.
+ /// Returns `None` if `self` is `LevelFilter::Off`.
#[inline]
- pub fn to_log_level(&self) -> Option<LogLevel> {
- LogLevel::from_usize(*self as usize)
+ pub fn to_level(&self) -> Option<Level> {
+ Level::from_usize(*self as usize)
}
}
-/// The "payload" of a log message. This structure is primarily used as a
-/// parameter in the [`log`] method of the [`Log`] trait.
+/// The "payload" of a log message.
+///
+/// # Use
+///
+/// `Record` structures are passed as parameters to the [`log`][method.log]
+/// method of the [`Log`] trait. Logger implementors manipulate these
+/// structures in order to display log messages. `Record`s are automatically
+/// created by the [`log!`] macro and so are not seen by log users.
+///
+/// Note that the [`level()`] and [`target()`] accessors are equivalent to
+/// `self.metadata().level()` and `self.metadata().target()` respectively.
+/// These methods are provided as a convenience for users of this structure.
+///
+/// # Example
+///
+/// The following example shows a simple logger that displays the level,
+/// module path, and message of any `Record` that is passed to it.
///
-/// [`log`]: trait.Log.html#tymethod.log
+/// ```rust
+/// # extern crate log;
+/// struct SimpleLogger;
+///
+/// impl log::Log for SimpleLogger {
+/// fn enabled(&self, metadata: &log::Metadata) -> bool {
+/// true
+/// }
+///
+/// fn log(&self, record: &log::Record) {
+/// if !self.enabled(record.metadata()) {
+/// return;
+/// }
+///
+/// println!("{}:{} -- {}",
+/// record.level(),
+/// record.target(),
+/// record.args());
+/// }
+/// fn flush(&self) {}
+/// }
+/// ```
+///
+/// [method.log]: trait.Log.html#tymethod.log
/// [`Log`]: trait.Log.html
-#[derive(Debug)]
-pub struct LogRecord<'a> {
- metadata: LogMetadata<'a>,
- location: &'a LogLocation,
+/// [`log!`]: macro.log.html
+/// [`level()`]: struct.Record.html#method.level
+/// [`target()`]: struct.Record.html#method.target
+#[derive(Clone, Debug)]
+pub struct Record<'a> {
+ metadata: Metadata<'a>,
args: fmt::Arguments<'a>,
+ module_path: Option<&'a str>,
+ file: Option<&'a str>,
+ line: Option<u32>,
}
-impl<'a> LogRecord<'a> {
+impl<'a> Record<'a> {
+ /// Returns a new builder.
+ #[inline]
+ pub fn builder() -> RecordBuilder<'a> {
+ RecordBuilder::new()
+ }
+
/// The message body.
+ #[inline]
pub fn args(&self) -> &fmt::Arguments<'a> {
&self.args
}
/// Metadata about the log directive.
- pub fn metadata(&self) -> &LogMetadata {
+ #[inline]
+ pub fn metadata(&self) -> &Metadata<'a> {
&self.metadata
}
- /// The location of the log directive.
- pub fn location(&self) -> &LogLocation {
- self.location
- }
-
/// The verbosity level of the message.
- pub fn level(&self) -> LogLevel {
+ #[inline]
+ pub fn level(&self) -> Level {
self.metadata.level()
}
/// The name of the target of the directive.
- pub fn target(&self) -> &str {
+ #[inline]
+ pub fn target(&self) -> &'a str {
self.metadata.target()
}
+
+ /// The module path of the message.
+ #[inline]
+ pub fn module_path(&self) -> Option<&'a str> {
+ self.module_path
+ }
+
+ /// The source file containing the message.
+ #[inline]
+ pub fn file(&self) -> Option<&'a str> {
+ self.file
+ }
+
+ /// The line containing the message.
+ #[inline]
+ pub fn line(&self) -> Option<u32> {
+ self.line
+ }
+}
+
+/// Builder for [`Record`](struct.Record.html).
+///
+/// Typically should only be used by log library creators or for testing and "shim loggers".
+/// The `RecordBuilder` can set the different parameters of `Record` object, and returns
+/// the created object when `build` is called.
+///
+/// # Examples
+///
+///
+/// ```rust
+/// use log::{Level, Record};
+///
+/// let record = Record::builder()
+/// .args(format_args!("Error!"))
+/// .level(Level::Error)
+/// .target("myApp")
+/// .file(Some("server.rs"))
+/// .line(Some(144))
+/// .module_path(Some("server"))
+/// .build();
+/// ```
+///
+/// Alternatively, use [`MetadataBuilder`](struct.MetadataBuilder.html):
+///
+/// ```rust
+/// use log::{Record, Level, MetadataBuilder};
+///
+/// let error_metadata = MetadataBuilder::new()
+/// .target("myApp")
+/// .level(Level::Error)
+/// .build();
+///
+/// let record = Record::builder()
+/// .metadata(error_metadata)
+/// .args(format_args!("Error!"))
+/// .line(Some(433))
+/// .file(Some("app.rs"))
+/// .module_path(Some("server"))
+/// .build();
+/// ```
+#[derive(Debug)]
+pub struct RecordBuilder<'a> {
+ record: Record<'a>,
+}
+
+impl<'a> RecordBuilder<'a> {
+ /// Construct new `RecordBuilder`.
+ ///
+ /// The default options are:
+ ///
+ /// - `args`: [`format_args!("")`]
+ /// - `metadata`: [`Metadata::builder().build()`]
+ /// - `module_path`: `None`
+ /// - `file`: `None`
+ /// - `line`: `None`
+ ///
+ /// [`format_args!("")`]: https://doc.rust-lang.org/std/macro.format_args.html
+ /// [`Metadata::builder().build()`]: struct.MetadataBuilder.html#method.build
+ #[inline]
+ pub fn new() -> RecordBuilder<'a> {
+ RecordBuilder {
+ record: Record {
+ args: format_args!(""),
+ metadata: Metadata::builder().build(),
+ module_path: None,
+ file: None,
+ line: None,
+ },
+ }
+ }
+
+ /// Set [`args`](struct.Record.html#method.args).
+ #[inline]
+ pub fn args(&mut self, args: fmt::Arguments<'a>) -> &mut RecordBuilder<'a> {
+ self.record.args = args;
+ self
+ }
+
+ /// Set [`metadata`](struct.Record.html#method.metadata). Construct a `Metadata` object with [`MetadataBuilder`](struct.MetadataBuilder.html).
+ #[inline]
+ pub fn metadata(&mut self, metadata: Metadata<'a>) -> &mut RecordBuilder<'a> {
+ self.record.metadata = metadata;
+ self
+ }
+
+ /// Set [`Metadata::level`](struct.Metadata.html#method.level).
+ #[inline]
+ pub fn level(&mut self, level: Level) -> &mut RecordBuilder<'a> {
+ self.record.metadata.level = level;
+ self
+ }
+
+ /// Set [`Metadata::target`](struct.Metadata.html#method.target)
+ #[inline]
+ pub fn target(&mut self, target: &'a str) -> &mut RecordBuilder<'a> {
+ self.record.metadata.target = target;
+ self
+ }
+
+ /// Set [`module_path`](struct.Record.html#method.module_path)
+ #[inline]
+ pub fn module_path(&mut self, path: Option<&'a str>) -> &mut RecordBuilder<'a> {
+ self.record.module_path = path;
+ self
+ }
+
+ /// Set [`file`](struct.Record.html#method.file)
+ #[inline]
+ pub fn file(&mut self, file: Option<&'a str>) -> &mut RecordBuilder<'a> {
+ self.record.file = file;
+ self
+ }
+
+ /// Set [`line`](struct.Record.html#method.line)
+ #[inline]
+ pub fn line(&mut self, line: Option<u32>) -> &mut RecordBuilder<'a> {
+ self.record.line = line;
+ self
+ }
+
+ /// Invoke the builder and return a `Record`
+ #[inline]
+ pub fn build(&self) -> Record<'a> {
+ self.record.clone()
+ }
}
/// Metadata about a log message.
-#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
-pub struct LogMetadata<'a> {
- level: LogLevel,
+///
+/// # Use
+///
+/// `Metadata` structs are created when users of the library use
+/// logging macros.
+///
+/// They are consumed by implementations of the `Log` trait in the
+/// `enabled` method.
+///
+/// `Record`s use `Metadata` to determine the log message's severity
+/// and target.
+///
+/// Users should use the `log_enabled!` macro in their code to avoid
+/// constructing expensive log messages.
+///
+/// # Examples
+///
+/// ```rust
+/// # #[macro_use]
+/// # extern crate log;
+/// #
+/// use log::{Record, Level, Metadata};
+///
+/// struct MyLogger;
+///
+/// impl log::Log for MyLogger {
+/// fn enabled(&self, metadata: &Metadata) -> bool {
+/// metadata.level() <= Level::Info
+/// }
+///
+/// fn log(&self, record: &Record) {
+/// if self.enabled(record.metadata()) {
+/// println!("{} - {}", record.level(), record.args());
+/// }
+/// }
+/// fn flush(&self) {}
+/// }
+///
+/// # fn main(){}
+/// ```
+#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
+pub struct Metadata<'a> {
+ level: Level,
target: &'a str,
}
-impl<'a> LogMetadata<'a> {
+impl<'a> Metadata<'a> {
+ /// Returns a new builder.
+ #[inline]
+ pub fn builder() -> MetadataBuilder<'a> {
+ MetadataBuilder::new()
+ }
+
/// The verbosity level of the message.
- pub fn level(&self) -> LogLevel {
+ #[inline]
+ pub fn level(&self) -> Level {
self.level
}
/// The name of the target of the directive.
- pub fn target(&self) -> &str {
+ #[inline]
+ pub fn target(&self) -> &'a str {
self.target
}
}
-/// A trait encapsulating the operations required of a logger
-pub trait Log: Sync+Send {
+/// Builder for [`Metadata`](struct.Metadata.html).
+///
+/// Typically should only be used by log library creators or for testing and "shim loggers".
+/// The `MetadataBuilder` can set the different parameters of a `Metadata` object, and returns
+/// the created object when `build` is called.
+///
+/// # Example
+///
+/// ```rust
+/// let target = "myApp";
+/// use log::{Level, MetadataBuilder};
+/// let metadata = MetadataBuilder::new()
+/// .level(Level::Debug)
+/// .target(target)
+/// .build();
+/// ```
+#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
+pub struct MetadataBuilder<'a> {
+ metadata: Metadata<'a>,
+}
+
+impl<'a> MetadataBuilder<'a> {
+ /// Construct a new `MetadataBuilder`.
+ ///
+ /// The default options are:
+ ///
+ /// - `level`: `Level::Info`
+ /// - `target`: `""`
+ #[inline]
+ pub fn new() -> MetadataBuilder<'a> {
+ MetadataBuilder {
+ metadata: Metadata {
+ level: Level::Info,
+ target: "",
+ },
+ }
+ }
+
+ /// Setter for [`level`](struct.Metadata.html#method.level).
+ #[inline]
+ pub fn level(&mut self, arg: Level) -> &mut MetadataBuilder<'a> {
+ self.metadata.level = arg;
+ self
+ }
+
+ /// Setter for [`target`](struct.Metadata.html#method.target).
+ #[inline]
+ pub fn target(&mut self, target: &'a str) -> &mut MetadataBuilder<'a> {
+ self.metadata.target = target;
+ self
+ }
+
+ /// Returns a `Metadata` object.
+ #[inline]
+ pub fn build(&self) -> Metadata<'a> {
+ self.metadata.clone()
+ }
+}
+
+/// A trait encapsulating the operations required of a logger.
+pub trait Log: Sync + Send {
/// Determines if a log message with the specified metadata would be
/// logged.
///
/// This is used by the `log_enabled!` macro to allow callers to avoid
/// expensive computation of log message arguments if the message would be
/// discarded anyway.
- fn enabled(&self, metadata: &LogMetadata) -> bool;
+ fn enabled(&self, metadata: &Metadata) -> bool;
- /// Logs the `LogRecord`.
+ /// Logs the `Record`.
///
/// Note that `enabled` is *not* necessarily called before this method.
/// Implementations of `log` should perform all necessary filtering
/// internally.
- fn log(&self, record: &LogRecord);
+ fn log(&self, record: &Record);
+
+ /// Flushes any buffered records.
+ fn flush(&self);
}
// Just used as a dummy initial value for LOGGER
struct NopLogger;
impl Log for NopLogger {
- fn enabled(&self, _: &LogMetadata) -> bool { false }
-
- fn log(&self, _: &LogRecord) {}
-}
-
-/// The location of a log message.
-///
-/// # Warning
-///
-/// The fields of this struct are public so that they may be initialized by the
-/// `log!` macro. They are subject to change at any time and should never be
-/// accessed directly.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
-pub struct LogLocation {
- #[doc(hidden)]
- pub __module_path: &'static str,
- #[doc(hidden)]
- pub __file: &'static str,
- #[doc(hidden)]
- pub __line: u32,
-}
-
-impl LogLocation {
- /// The module path of the message.
- pub fn module_path(&self) -> &str {
- self.__module_path
- }
-
- /// The source file containing the message.
- pub fn file(&self) -> &str {
- self.__file
+ fn enabled(&self, _: &Metadata) -> bool {
+ false
}
- /// The line containing the message.
- pub fn line(&self) -> u32 {
- self.__line
- }
+ fn log(&self, _: &Record) {}
+ fn flush(&self) {}
}
-/// A token providing read and write access to the global maximum log level
-/// filter.
+/// Sets the global maximum log level.
///
-/// The maximum log level is used as an optimization to avoid evaluating log
-/// messages that will be ignored by the logger. Any message with a level
-/// higher than the maximum log level filter will be ignored. A logger should
-/// make sure to keep the maximum log level filter in sync with its current
-/// configuration.
-#[allow(missing_copy_implementations)]
-pub struct MaxLogLevelFilter(());
-
-impl fmt::Debug for MaxLogLevelFilter {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- write!(fmt, "MaxLogLevelFilter")
- }
-}
-
-impl MaxLogLevelFilter {
- /// Gets the current maximum log level filter.
- pub fn get(&self) -> LogLevelFilter {
- max_log_level()
- }
-
- /// Sets the maximum log level.
- pub fn set(&self, level: LogLevelFilter) {
- MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::SeqCst)
- }
+/// Generally, this should only be called by the active logging implementation.
+#[inline]
+pub fn set_max_level(level: LevelFilter) {
+ MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::SeqCst)
}
/// Returns the current maximum log level.
///
-/// The `log!`, `error!`, `warn!`, `info!`, `debug!`, and `trace!` macros check
+/// The [`log!`], [`error!`], [`warn!`], [`info!`], [`debug!`], and [`trace!`] macros check
/// this value and discard any message logged at a higher level. The maximum
-/// log level is set by the `MaxLogLevel` token passed to loggers.
+/// log level is set by the [`set_max_level`] function.
+///
+/// [`log!`]: macro.log.html
+/// [`error!`]: macro.error.html
+/// [`warn!`]: macro.warn.html
+/// [`info!`]: macro.info.html
+/// [`debug!`]: macro.debug.html
+/// [`trace!`]: macro.trace.html
+/// [`set_max_level`]: fn.set_max_level.html
#[inline(always)]
-pub fn max_log_level() -> LogLevelFilter {
+pub fn max_level() -> LevelFilter {
unsafe { mem::transmute(MAX_LOG_LEVEL_FILTER.load(Ordering::Relaxed)) }
}
-/// Sets the global logger.
+/// Sets the global logger to a `Box<Log>`.
+///
+/// This is a simple convenience wrapper over `set_logger`, which takes a
+/// `Box<Log>` rather than a `&'static Log`. See the documentation for
+/// [`set_logger`] for more details.
+///
+/// Requires the `std` feature.
+///
+/// # Errors
///
-/// The `make_logger` closure is passed a `MaxLogLevel` object, which the
-/// logger should use to keep the global maximum log level in sync with the
-/// highest log level that the logger will not ignore.
+/// An error is returned if a logger has already been set.
+///
+/// [`set_logger`]: fn.set_logger.html
+#[cfg(feature = "std")]
+pub fn set_boxed_logger(logger: Box<Log>) -> Result<(), SetLoggerError> {
+ set_logger_inner(|| unsafe { &*Box::into_raw(logger) })
+}
+
+/// Sets the global logger to a `&'static Log`.
///
/// This function may only be called once in the lifetime of a program. Any log
-/// events that occur before the call to `set_logger` completes will be
-/// ignored.
-///
-/// This function does not typically need to be called manually. Logger
-/// implementations should provide an initialization method that calls
-/// `set_logger` internally.
-///
-/// Requires the `use_std` feature (enabled by default).
-#[cfg(feature = "use_std")]
-pub fn set_logger<M>(make_logger: M) -> Result<(), SetLoggerError>
- where M: FnOnce(MaxLogLevelFilter) -> Box<Log> {
- unsafe { set_logger_raw(|max_level| mem::transmute(make_logger(max_level))) }
-}
-
-/// Sets the global logger from a raw pointer.
-///
-/// This function is similar to `set_logger` except that it is usable in
-/// `no_std` code.
-///
-/// The `make_logger` closure is passed a `MaxLogLevel` object, which the
-/// logger should use to keep the global maximum log level in sync with the
-/// highest log level that the logger will not ignore.
-///
-/// This function may only be called once in the lifetime of a program. Any log
-/// events that occur before the call to `set_logger_raw` completes will be
-/// ignored.
+/// events that occur before the call to `set_logger` completes will be ignored.
///
/// This function does not typically need to be called manually. Logger
-/// implementations should provide an initialization method that calls
-/// `set_logger_raw` internally.
+/// implementations should provide an initialization method that installs the
+/// logger internally.
+///
+/// # Errors
+///
+/// An error is returned if a logger has already been set.
+///
+/// # Examples
///
-/// # Safety
+/// ```rust
+/// # #[macro_use]
+/// # extern crate log;
+/// #
+/// use log::{Record, Level, Metadata, LevelFilter};
+///
+/// static MY_LOGGER: MyLogger = MyLogger;
+///
+/// struct MyLogger;
///
-/// The pointer returned by `make_logger` must remain valid for the entire
-/// duration of the program or until `shutdown_logger_raw` is called. In
-/// addition, `shutdown_logger` *must not* be called after this function.
-pub unsafe fn set_logger_raw<M>(make_logger: M) -> Result<(), SetLoggerError>
- where M: FnOnce(MaxLogLevelFilter) -> *const Log {
- if STATE.compare_and_swap(UNINITIALIZED, INITIALIZING,
- Ordering::SeqCst) != UNINITIALIZED {
- return Err(SetLoggerError(()));
- }
-
- LOGGER = make_logger(MaxLogLevelFilter(()));
- STATE.store(INITIALIZED, Ordering::SeqCst);
- Ok(())
+/// impl log::Log for MyLogger {
+/// fn enabled(&self, metadata: &Metadata) -> bool {
+/// metadata.level() <= Level::Info
+/// }
+///
+/// fn log(&self, record: &Record) {
+/// if self.enabled(record.metadata()) {
+/// println!("{} - {}", record.level(), record.args());
+/// }
+/// }
+/// fn flush(&self) {}
+/// }
+///
+/// # fn main(){
+/// log::set_logger(&MY_LOGGER).unwrap();
+/// log::set_max_level(LevelFilter::Info);
+///
+/// info!("hello log");
+/// warn!("warning");
+/// error!("oops");
+/// # }
+/// ```
+pub fn set_logger(logger: &'static Log) -> Result<(), SetLoggerError> {
+ set_logger_inner(|| logger)
}
-/// Shuts down the global logger.
-///
-/// This function may only be called once in the lifetime of a program, and may
-/// not be called before `set_logger`. Once the global logger has been shut
-/// down, it can no longer be re-initialized by `set_logger`. Any log events
-/// that occur after the call to `shutdown_logger` completes will be ignored.
-///
-/// The logger that was originally created by the call to to `set_logger` is
-/// returned on success. At that point it is guaranteed that no other threads
-/// are concurrently accessing the logger object.
-#[cfg(feature = "use_std")]
-pub fn shutdown_logger() -> Result<Box<Log>, ShutdownLoggerError> {
- shutdown_logger_raw().map(|l| unsafe { mem::transmute(l) })
-}
+fn set_logger_inner<F>(make_logger: F) -> Result<(), SetLoggerError>
+where
+ F: FnOnce() -> &'static Log
+{
+ unsafe {
+ if STATE.compare_and_swap(UNINITIALIZED, INITIALIZING, Ordering::SeqCst) != UNINITIALIZED {
+ return Err(SetLoggerError(()));
+ }
-/// Shuts down the global logger.
-///
-/// This function is similar to `shutdown_logger` except that it is usable in
-/// `no_std` code.
-///
-/// This function may only be called once in the lifetime of a program, and may
-/// not be called before `set_logger_raw`. Once the global logger has been shut
-/// down, it can no longer be re-initialized by `set_logger_raw`. Any log
-/// events that occur after the call to `shutdown_logger_raw` completes will be
-/// ignored.
-///
-/// The pointer that was originally passed to `set_logger_raw` is returned on
-/// success. At that point it is guaranteed that no other threads are
-/// concurrently accessing the logger object.
-pub fn shutdown_logger_raw() -> Result<*const Log, ShutdownLoggerError> {
- // Set the global log level to stop other thread from logging
- MAX_LOG_LEVEL_FILTER.store(0, Ordering::SeqCst);
-
- // Set to INITIALIZING to prevent re-initialization after
- if STATE.compare_and_swap(INITIALIZED, INITIALIZING,
- Ordering::SeqCst) != INITIALIZED {
- return Err(ShutdownLoggerError(()));
- }
-
- while REFCOUNT.load(Ordering::SeqCst) != 0 {
- // FIXME add a sleep here when it doesn't involve timers
- }
-
- unsafe {
- let logger = LOGGER;
- LOGGER = &NopLogger;
- Ok(logger)
+ LOGGER = make_logger();
+ STATE.store(INITIALIZED, Ordering::SeqCst);
+ Ok(())
}
}
-/// The type returned by `set_logger` if `set_logger` has already been called.
+/// The type returned by [`set_logger`] if [`set_logger`] has already been called.
+///
+/// [`set_logger`]: fn.set_logger.html
#[allow(missing_copy_implementations)]
#[derive(Debug)]
pub struct SetLoggerError(());
impl fmt::Display for SetLoggerError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- write!(fmt, "attempted to set a logger after the logging system \
- was already initialized")
- }
-}
-
-// The Error trait is not available in libcore
-#[cfg(feature = "use_std")]
-impl error::Error for SetLoggerError {
- fn description(&self) -> &str { "set_logger() called multiple times" }
-}
-
-/// The type returned by `shutdown_logger_raw` if `shutdown_logger_raw` has
-/// already been called or if `set_logger_raw` has not been called yet.
-#[allow(missing_copy_implementations)]
-#[derive(Debug)]
-pub struct ShutdownLoggerError(());
-
-impl fmt::Display for ShutdownLoggerError {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- write!(fmt, "attempted to shut down the logger without an active logger")
+ fmt.write_str(SET_LOGGER_ERROR)
}
}
// The Error trait is not available in libcore
-#[cfg(feature = "use_std")]
-impl error::Error for ShutdownLoggerError {
- fn description(&self) -> &str { "shutdown_logger() called without an active logger" }
-}
-
-/// Deprecated
-///
-/// Use https://crates.io/crates/log-panics instead.
-#[cfg(all(feature = "nightly", feature = "use_std"))]
-pub fn log_panics() {
- std::panic::set_hook(Box::new(panic::log));
+#[cfg(feature = "std")]
+impl error::Error for SetLoggerError {
+ fn description(&self) -> &str {
+ SET_LOGGER_ERROR
+ }
}
-// inner module so that the reporting module is log::panic instead of log
-#[cfg(all(feature = "nightly", feature = "use_std"))]
-mod panic {
- use std::panic::PanicInfo;
- use std::thread;
+/// The type returned by [`from_str`] when the string doesn't match any of the log levels.
+///
+/// [`from_str`]: https://doc.rust-lang.org/std/str/trait.FromStr.html#tymethod.from_str
+#[allow(missing_copy_implementations)]
+#[derive(Debug, PartialEq)]
+pub struct ParseLevelError(());
- pub fn log(info: &PanicInfo) {
- let thread = thread::current();
- let thread = thread.name().unwrap_or("<unnamed>");
+impl fmt::Display for ParseLevelError {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.write_str(LEVEL_PARSE_ERROR)
+ }
+}
- let msg = match info.payload().downcast_ref::<&'static str>() {
- Some(s) => *s,
- None => match info.payload().downcast_ref::<String>() {
- Some(s) => &s[..],
- None => "Box<Any>",
- }
- };
+// The Error trait is not available in libcore
+#[cfg(feature = "std")]
+impl error::Error for ParseLevelError {
+ fn description(&self) -> &str {
+ LEVEL_PARSE_ERROR
+ }
+}
- match info.location() {
- Some(location) => {
- error!("thread '{}' panicked at '{}': {}:{}",
- thread,
- msg,
- location.file(),
- location.line())
- }
- None => error!("thread '{}' panicked at '{}'", thread, msg),
+/// Returns a reference to the logger.
+///
+/// If a logger has not been set, a no-op implementation is returned.
+pub fn logger() -> &'static Log {
+ unsafe {
+ if STATE.load(Ordering::SeqCst) != INITIALIZED {
+ static NOP: NopLogger = NopLogger;
+ &NOP
+ } else {
+ LOGGER
}
}
}
-struct LoggerGuard(&'static Log);
-
-impl Drop for LoggerGuard {
- fn drop(&mut self) {
- REFCOUNT.fetch_sub(1, Ordering::SeqCst);
- }
-}
-
-impl Deref for LoggerGuard {
- type Target = Log;
-
- fn deref(&self) -> &(Log + 'static) {
- self.0
- }
-}
-
-fn logger() -> Option<LoggerGuard> {
- REFCOUNT.fetch_add(1, Ordering::SeqCst);
- if STATE.load(Ordering::SeqCst) != INITIALIZED {
- REFCOUNT.fetch_sub(1, Ordering::SeqCst);
- None
- } else {
- Some(LoggerGuard(unsafe { &*LOGGER }))
- }
-}
-
-// WARNING
-// This is not considered part of the crate's public API. It is subject to
-// change at any time.
-#[doc(hidden)]
-pub fn __enabled(level: LogLevel, target: &str) -> bool {
- if let Some(logger) = logger() {
- logger.enabled(&LogMetadata { level: level, target: target })
- } else {
- false
- }
-}
+/// The statically resolved maximum log level.
+///
+/// See the crate level documentation for information on how to configure this.
+///
+/// This value is checked by the log macros, but not by the `Log`ger returned by
+/// the [`logger`] function. Code that manually calls functions on that value
+/// should compare the level against this value.
+///
+/// [`logger`]: fn.logger.html
+pub const STATIC_MAX_LEVEL: LevelFilter = MAX_LEVEL_INNER;
-// WARNING
-// This is not considered part of the crate's public API. It is subject to
-// change at any time.
-#[doc(hidden)]
-pub fn __log(level: LogLevel, target: &str, loc: &LogLocation,
- args: fmt::Arguments) {
- if let Some(logger) = logger() {
- let record = LogRecord {
- metadata: LogMetadata {
- level: level,
- target: target,
- },
- location: loc,
- args: args
- };
- logger.log(&record)
- }
-}
-
-// WARNING
-// This is not considered part of the crate's public API. It is subject to
-// change at any time.
-#[inline(always)]
-#[doc(hidden)]
-pub fn __static_max_level() -> LogLevelFilter {
- if !cfg!(debug_assertions) {
- // This is a release build. Check `release_max_level_*` first.
- if cfg!(feature = "release_max_level_off") {
- return LogLevelFilter::Off
- } else if cfg!(feature = "release_max_level_error") {
- return LogLevelFilter::Error
- } else if cfg!(feature = "release_max_level_warn") {
- return LogLevelFilter::Warn
- } else if cfg!(feature = "release_max_level_info") {
- return LogLevelFilter::Info
- } else if cfg!(feature = "release_max_level_debug") {
- return LogLevelFilter::Debug
- } else if cfg!(feature = "release_max_level_trace") {
- return LogLevelFilter::Trace
- }
- }
- if cfg!(feature = "max_level_off") {
- LogLevelFilter::Off
- } else if cfg!(feature = "max_level_error") {
- LogLevelFilter::Error
- } else if cfg!(feature = "max_level_warn") {
- LogLevelFilter::Warn
- } else if cfg!(feature = "max_level_info") {
- LogLevelFilter::Info
- } else if cfg!(feature = "max_level_debug") {
- LogLevelFilter::Debug
+cfg_if! {
+ if #[cfg(all(not(debug_assertions), feature = "release_max_level_off"))] {
+ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Off;
+ } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_error"))] {
+ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Error;
+ } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_warn"))] {
+ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Warn;
+ } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_info"))] {
+ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Info;
+ } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_debug"))] {
+ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Debug;
+ } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_trace"))] {
+ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Trace;
+ } else if #[cfg(feature = "max_level_off")] {
+ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Off;
+ } else if #[cfg(feature = "max_level_error")] {
+ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Error;
+ } else if #[cfg(feature = "max_level_warn")] {
+ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Warn;
+ } else if #[cfg(feature = "max_level_info")] {
+ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Info;
+ } else if #[cfg(feature = "max_level_debug")] {
+ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Debug;
} else {
- LogLevelFilter::Trace
+ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Trace;
}
}
#[cfg(test)]
mod tests {
- extern crate std;
- use tests::std::string::ToString;
- use super::{LogLevel, LogLevelFilter};
+ extern crate std;
+ use tests::std::string::ToString;
+ use super::{Level, LevelFilter, ParseLevelError};
+
+ #[test]
+ fn test_levelfilter_from_str() {
+ let tests = [
+ ("off", Ok(LevelFilter::Off)),
+ ("error", Ok(LevelFilter::Error)),
+ ("warn", Ok(LevelFilter::Warn)),
+ ("info", Ok(LevelFilter::Info)),
+ ("debug", Ok(LevelFilter::Debug)),
+ ("trace", Ok(LevelFilter::Trace)),
+ ("OFF", Ok(LevelFilter::Off)),
+ ("ERROR", Ok(LevelFilter::Error)),
+ ("WARN", Ok(LevelFilter::Warn)),
+ ("INFO", Ok(LevelFilter::Info)),
+ ("DEBUG", Ok(LevelFilter::Debug)),
+ ("TRACE", Ok(LevelFilter::Trace)),
+ ("asdf", Err(ParseLevelError(()))),
+ ];
+ for &(s, ref expected) in &tests {
+ assert_eq!(expected, &s.parse());
+ }
+ }
- #[test]
- fn test_loglevelfilter_from_str() {
- let tests = [
- ("off", Ok(LogLevelFilter::Off)),
- ("error", Ok(LogLevelFilter::Error)),
- ("warn", Ok(LogLevelFilter::Warn)),
- ("info", Ok(LogLevelFilter::Info)),
- ("debug", Ok(LogLevelFilter::Debug)),
- ("trace", Ok(LogLevelFilter::Trace)),
- ("OFF", Ok(LogLevelFilter::Off)),
- ("ERROR", Ok(LogLevelFilter::Error)),
- ("WARN", Ok(LogLevelFilter::Warn)),
- ("INFO", Ok(LogLevelFilter::Info)),
- ("DEBUG", Ok(LogLevelFilter::Debug)),
- ("TRACE", Ok(LogLevelFilter::Trace)),
- ("asdf", Err(())),
- ];
- for &(s, ref expected) in &tests {
- assert_eq!(expected, &s.parse());
- }
- }
+ #[test]
+ fn test_level_from_str() {
+ let tests = [
+ ("OFF", Err(ParseLevelError(()))),
+ ("error", Ok(Level::Error)),
+ ("warn", Ok(Level::Warn)),
+ ("info", Ok(Level::Info)),
+ ("debug", Ok(Level::Debug)),
+ ("trace", Ok(Level::Trace)),
+ ("ERROR", Ok(Level::Error)),
+ ("WARN", Ok(Level::Warn)),
+ ("INFO", Ok(Level::Info)),
+ ("DEBUG", Ok(Level::Debug)),
+ ("TRACE", Ok(Level::Trace)),
+ ("asdf", Err(ParseLevelError(()))),
+ ];
+ for &(s, ref expected) in &tests {
+ assert_eq!(expected, &s.parse());
+ }
+ }
+
+ #[test]
+ fn test_level_show() {
+ assert_eq!("INFO", Level::Info.to_string());
+ assert_eq!("ERROR", Level::Error.to_string());
+ }
- #[test]
- fn test_loglevel_from_str() {
- let tests = [
- ("OFF", Err(())),
- ("error", Ok(LogLevel::Error)),
- ("warn", Ok(LogLevel::Warn)),
- ("info", Ok(LogLevel::Info)),
- ("debug", Ok(LogLevel::Debug)),
- ("trace", Ok(LogLevel::Trace)),
- ("ERROR", Ok(LogLevel::Error)),
- ("WARN", Ok(LogLevel::Warn)),
- ("INFO", Ok(LogLevel::Info)),
- ("DEBUG", Ok(LogLevel::Debug)),
- ("TRACE", Ok(LogLevel::Trace)),
- ("asdf", Err(())),
- ];
- for &(s, ref expected) in &tests {
- assert_eq!(expected, &s.parse());
- }
- }
+ #[test]
+ fn test_levelfilter_show() {
+ assert_eq!("OFF", LevelFilter::Off.to_string());
+ assert_eq!("ERROR", LevelFilter::Error.to_string());
+ }
+
+ #[test]
+ fn test_cross_cmp() {
+ assert!(Level::Debug > LevelFilter::Error);
+ assert!(LevelFilter::Warn < Level::Trace);
+ assert!(LevelFilter::Off < Level::Error);
+ }
+
+ #[test]
+ fn test_cross_eq() {
+ assert!(Level::Error == LevelFilter::Error);
+ assert!(LevelFilter::Off != Level::Error);
+ assert!(Level::Trace == LevelFilter::Trace);
+ }
+
+ #[test]
+ fn test_to_level() {
+ assert_eq!(Some(Level::Error), LevelFilter::Error.to_level());
+ assert_eq!(None, LevelFilter::Off.to_level());
+ assert_eq!(Some(Level::Debug), LevelFilter::Debug.to_level());
+ }
+
+ #[test]
+ fn test_to_level_filter() {
+ assert_eq!(LevelFilter::Error, Level::Error.to_level_filter());
+ assert_eq!(LevelFilter::Trace, Level::Trace.to_level_filter());
+ }
- #[test]
- fn test_loglevel_show() {
- assert_eq!("INFO", LogLevel::Info.to_string());
- assert_eq!("ERROR", LogLevel::Error.to_string());
- }
+ #[test]
+ #[cfg(feature = "std")]
+ fn test_error_trait() {
+ use std::error::Error;
+ use super::SetLoggerError;
+ let e = SetLoggerError(());
+ assert_eq!(
+ e.description(),
+ "attempted to set a logger after the logging system \
+ was already initialized"
+ );
+ }
- #[test]
- fn test_loglevelfilter_show() {
- assert_eq!("OFF", LogLevelFilter::Off.to_string());
- assert_eq!("ERROR", LogLevelFilter::Error.to_string());
- }
+ #[test]
+ fn test_metadata_builder() {
+ use super::MetadataBuilder;
+ let target = "myApp";
+ let metadata_test = MetadataBuilder::new()
+ .level(Level::Debug)
+ .target(target)
+ .build();
+ assert_eq!(metadata_test.level(), Level::Debug);
+ assert_eq!(metadata_test.target(), "myApp");
+ }
- #[test]
- fn test_cross_cmp() {
- assert!(LogLevel::Debug > LogLevelFilter::Error);
- assert!(LogLevelFilter::Warn < LogLevel::Trace);
- assert!(LogLevelFilter::Off < LogLevel::Error);
- }
+ #[test]
+ fn test_metadata_convenience_builder() {
+ use super::Metadata;
+ let target = "myApp";
+ let metadata_test = Metadata::builder()
+ .level(Level::Debug)
+ .target(target)
+ .build();
+ assert_eq!(metadata_test.level(), Level::Debug);
+ assert_eq!(metadata_test.target(), "myApp");
+ }
- #[test]
- fn test_cross_eq() {
- assert!(LogLevel::Error == LogLevelFilter::Error);
- assert!(LogLevelFilter::Off != LogLevel::Error);
- assert!(LogLevel::Trace == LogLevelFilter::Trace);
- }
-
- #[test]
- fn test_to_log_level() {
- assert_eq!(Some(LogLevel::Error), LogLevelFilter::Error.to_log_level());
- assert_eq!(None, LogLevelFilter::Off.to_log_level());
- assert_eq!(Some(LogLevel::Debug), LogLevelFilter::Debug.to_log_level());
- }
+ #[test]
+ fn test_record_builder() {
+ use super::{MetadataBuilder, RecordBuilder};
+ let target = "myApp";
+ let metadata = MetadataBuilder::new().target(target).build();
+ let fmt_args = format_args!("hello");
+ let record_test = RecordBuilder::new()
+ .args(fmt_args)
+ .metadata(metadata)
+ .module_path(Some("foo"))
+ .file(Some("bar"))
+ .line(Some(30))
+ .build();
+ assert_eq!(record_test.metadata().target(), "myApp");
+ assert_eq!(record_test.module_path(), Some("foo"));
+ assert_eq!(record_test.file(), Some("bar"));
+ assert_eq!(record_test.line(), Some(30));
+ }
- #[test]
- fn test_to_log_level_filter() {
- assert_eq!(LogLevelFilter::Error, LogLevel::Error.to_log_level_filter());
- assert_eq!(LogLevelFilter::Trace, LogLevel::Trace.to_log_level_filter());
- }
+ #[test]
+ fn test_record_convenience_builder() {
+ use super::{Metadata, Record};
+ let target = "myApp";
+ let metadata = Metadata::builder().target(target).build();
+ let fmt_args = format_args!("hello");
+ let record_test = Record::builder()
+ .args(fmt_args)
+ .metadata(metadata)
+ .module_path(Some("foo"))
+ .file(Some("bar"))
+ .line(Some(30))
+ .build();
+ assert_eq!(record_test.target(), "myApp");
+ assert_eq!(record_test.module_path(), Some("foo"));
+ assert_eq!(record_test.file(), Some("bar"));
+ assert_eq!(record_test.line(), Some(30));
+ }
- #[test]
- #[cfg(feature = "use_std")]
- fn test_error_trait() {
- use std::error::Error;
- use super::SetLoggerError;
- let e = SetLoggerError(());
- assert_eq!(e.description(), "set_logger() called multiple times");
- }
+ #[test]
+ fn test_record_complete_builder() {
+ use super::{Record, Level};
+ let target = "myApp";
+ let record_test = Record::builder()
+ .module_path(Some("foo"))
+ .file(Some("bar"))
+ .line(Some(30))
+ .target(target)
+ .level(Level::Error)
+ .build();
+ assert_eq!(record_test.target(), "myApp");
+ assert_eq!(record_test.level(), Level::Error);
+ assert_eq!(record_test.module_path(), Some("foo"));
+ assert_eq!(record_test.file(), Some("bar"));
+ assert_eq!(record_test.line(), Some(30));
+ }
}
--- a/third_party/rust/log/src/macros.rs
+++ b/third_party/rust/log/src/macros.rs
@@ -2,123 +2,109 @@
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
/// The standard logging macro.
///
-/// This macro will generically log with the specified `LogLevel` and `format!`
+/// This macro will generically log with the specified `Level` and `format!`
/// based argument list.
///
-/// The `max_level_*` features can be used to statically disable logging at
-/// various levels.
-///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
-/// use log::LogLevel;
+/// use log::Level;
///
/// # fn main() {
/// let data = (42, "Forty-two");
/// let private_data = "private";
///
-/// log!(LogLevel::Error, "Received errors: {}, {}", data.0, data.1);
-/// log!(target: "app_events", LogLevel::Warn, "App warning: {}, {}, {}",
+/// log!(Level::Error, "Received errors: {}, {}", data.0, data.1);
+/// log!(target: "app_events", Level::Warn, "App warning: {}, {}, {}",
/// data.0, data.1, private_data);
/// # }
/// ```
#[macro_export]
macro_rules! log {
(target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
- static _LOC: $crate::LogLocation = $crate::LogLocation {
- __line: line!(),
- __file: file!(),
- __module_path: module_path!(),
- };
let lvl = $lvl;
- if lvl <= $crate::__static_max_level() && lvl <= $crate::max_log_level() {
- $crate::__log(lvl, $target, &_LOC, format_args!($($arg)+))
+ if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() {
+ $crate::Log::log(
+ $crate::logger(),
+ &$crate::RecordBuilder::new()
+ .args(format_args!($($arg)+))
+ .level(lvl)
+ .target($target)
+ .module_path(Some(module_path!()))
+ .file(Some(file!()))
+ .line(Some(line!()))
+ .build()
+ )
}
});
($lvl:expr, $($arg:tt)+) => (log!(target: module_path!(), $lvl, $($arg)+))
}
/// Logs a message at the error level.
///
-/// Logging at this level is disabled if the `max_level_off` feature is present.
-///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// let (err_info, port) = ("No connection", 22);
///
/// error!("Error: {} on port {}", err_info, port);
/// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22);
/// # }
/// ```
#[macro_export]
macro_rules! error {
(target: $target:expr, $($arg:tt)*) => (
- log!(target: $target, $crate::LogLevel::Error, $($arg)*);
+ log!(target: $target, $crate::Level::Error, $($arg)*);
);
($($arg:tt)*) => (
- log!($crate::LogLevel::Error, $($arg)*);
+ log!($crate::Level::Error, $($arg)*);
)
}
/// Logs a message at the warn level.
///
-/// Logging at this level is disabled if any of the following features are
-/// present: `max_level_off` or `max_level_error`.
-///
-/// When building in release mode (i.e., without the `debug_assertions` option),
-/// logging at this level is also disabled if any of the following features are
-/// present: `release_max_level_off` or `max_level_error`.
-///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// let warn_description = "Invalid Input";
///
/// warn!("Warning! {}!", warn_description);
/// warn!(target: "input_events", "App received warning: {}", warn_description);
/// # }
/// ```
#[macro_export]
macro_rules! warn {
(target: $target:expr, $($arg:tt)*) => (
- log!(target: $target, $crate::LogLevel::Warn, $($arg)*);
+ log!(target: $target, $crate::Level::Warn, $($arg)*);
);
($($arg:tt)*) => (
- log!($crate::LogLevel::Warn, $($arg)*);
+ log!($crate::Level::Warn, $($arg)*);
)
}
/// Logs a message at the info level.
///
-/// Logging at this level is disabled if any of the following features are
-/// present: `max_level_off`, `max_level_error`, or `max_level_warn`.
-///
-/// When building in release mode (i.e., without the `debug_assertions` option),
-/// logging at this level is also disabled if any of the following features are
-/// present: `release_max_level_off`, `release_max_level_error`, or
-/// `release_max_level_warn`.
-///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Connection { port: u32, speed: f32 }
/// let conn_info = Connection { port: 40, speed: 3.20 };
@@ -126,69 +112,50 @@ macro_rules! warn {
/// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed);
/// info!(target: "connection_events", "Successfull connection, port: {}, speed: {}",
/// conn_info.port, conn_info.speed);
/// # }
/// ```
#[macro_export]
macro_rules! info {
(target: $target:expr, $($arg:tt)*) => (
- log!(target: $target, $crate::LogLevel::Info, $($arg)*);
+ log!(target: $target, $crate::Level::Info, $($arg)*);
);
($($arg:tt)*) => (
- log!($crate::LogLevel::Info, $($arg)*);
+ log!($crate::Level::Info, $($arg)*);
)
}
/// Logs a message at the debug level.
///
-/// Logging at this level is disabled if any of the following features are
-/// present: `max_level_off`, `max_level_error`, `max_level_warn`, or
-/// `max_level_info`.
-///
-/// When building in release mode (i.e., without the `debug_assertions` option),
-/// logging at this level is also disabled if any of the following features are
-/// present: `release_max_level_off`, `release_max_level_error`,
-/// `release_max_level_warn`, or `release_max_level_info`.
-///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// debug!("New position: x: {}, y: {}", pos.x, pos.y);
/// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y);
/// # }
/// ```
#[macro_export]
macro_rules! debug {
(target: $target:expr, $($arg:tt)*) => (
- log!(target: $target, $crate::LogLevel::Debug, $($arg)*);
+ log!(target: $target, $crate::Level::Debug, $($arg)*);
);
($($arg:tt)*) => (
- log!($crate::LogLevel::Debug, $($arg)*);
+ log!($crate::Level::Debug, $($arg)*);
)
}
/// Logs a message at the trace level.
///
-/// Logging at this level is disabled if any of the following features are
-/// present: `max_level_off`, `max_level_error`, `max_level_warn`,
-/// `max_level_info`, or `max_level_debug`.
-///
-/// When building in release mode (i.e., without the `debug_assertions` option),
-/// logging at this level is also disabled if any of the following features are
-/// present: `release_max_level_off`, `release_max_level_error`,
-/// `release_max_level_warn`, `release_max_level_info`, or
-/// `release_max_level_debug`.
-///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
@@ -197,47 +164,57 @@ macro_rules! debug {
/// trace!(target: "app_events", "x is {} and y is {}",
/// if pos.x >= 0.0 { "positive" } else { "negative" },
/// if pos.y >= 0.0 { "positive" } else { "negative" });
/// # }
/// ```
#[macro_export]
macro_rules! trace {
(target: $target:expr, $($arg:tt)*) => (
- log!(target: $target, $crate::LogLevel::Trace, $($arg)*);
+ log!(target: $target, $crate::Level::Trace, $($arg)*);
);
($($arg:tt)*) => (
- log!($crate::LogLevel::Trace, $($arg)*);
+ log!($crate::Level::Trace, $($arg)*);
)
}
/// Determines if a message logged at the specified level in that module will
/// be logged.
///
/// This can be used to avoid expensive computation of log message arguments if
/// the message would be ignored anyway.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
-/// use log::LogLevel::Debug;
+/// use log::Level::Debug;
///
/// # fn foo() {
/// if log_enabled!(Debug) {
/// let data = expensive_call();
/// debug!("expensive debug data: {} {}", data.x, data.y);
/// }
+/// if log_enabled!(target: "Global", Debug) {
+/// let data = expensive_call();
+/// debug!(target: "Global", "expensive debug data: {} {}", data.x, data.y);
+/// }
/// # }
/// # struct Data { x: u32, y: u32 }
/// # fn expensive_call() -> Data { Data { x: 0, y: 0 } }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! log_enabled {
(target: $target:expr, $lvl:expr) => ({
let lvl = $lvl;
- lvl <= $crate::__static_max_level() && lvl <= $crate::max_log_level() &&
- $crate::__enabled(lvl, $target)
+ lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() &&
+ $crate::Log::enabled(
+ $crate::logger(),
+ &$crate::MetadataBuilder::new()
+ .level(lvl)
+ .target($target)
+ .build(),
+ )
});
($lvl:expr) => (log_enabled!(target: module_path!(), $lvl))
}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/log/src/serde.rs
@@ -0,0 +1,258 @@
+#![cfg(feature = "serde")]
+
+extern crate serde;
+use self::serde::ser::{Serialize, Serializer};
+use self::serde::de::{Deserialize, DeserializeSeed, Deserializer, Visitor, EnumAccess,
+ VariantAccess, Error};
+
+use {Level, LevelFilter, LOG_LEVEL_NAMES};
+
+use std::fmt;
+use std::str::FromStr;
+
+// The Deserialize impls are handwritten to be case insensitive using FromStr.
+
+impl Serialize for Level {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ match *self {
+ Level::Error => serializer.serialize_unit_variant("Level", 0, "ERROR"),
+ Level::Warn => serializer.serialize_unit_variant("Level", 1, "WARN"),
+ Level::Info => serializer.serialize_unit_variant("Level", 2, "INFO"),
+ Level::Debug => serializer.serialize_unit_variant("Level", 3, "DEBUG"),
+ Level::Trace => serializer.serialize_unit_variant("Level", 4, "TRACE"),
+ }
+ }
+}
+
+impl<'de> Deserialize<'de> for Level {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ struct LevelIdentifier;
+
+ impl<'de> Visitor<'de> for LevelIdentifier {
+ type Value = Level;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("log level")
+ }
+
+ fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ // Case insensitive.
+ FromStr::from_str(s).map_err(|_| Error::unknown_variant(s, &LOG_LEVEL_NAMES[1..]))
+ }
+ }
+
+ impl<'de> DeserializeSeed<'de> for LevelIdentifier {
+ type Value = Level;
+
+ fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ deserializer.deserialize_identifier(LevelIdentifier)
+ }
+ }
+
+ struct LevelEnum;
+
+ impl<'de> Visitor<'de> for LevelEnum {
+ type Value = Level;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("log level")
+ }
+
+ fn visit_enum<A>(self, value: A) -> Result<Self::Value, A::Error>
+ where
+ A: EnumAccess<'de>,
+ {
+ let (level, variant) = value.variant_seed(LevelIdentifier)?;
+ // Every variant is a unit variant.
+ variant.unit_variant()?;
+ Ok(level)
+ }
+ }
+
+ deserializer.deserialize_enum("Level", &LOG_LEVEL_NAMES[1..], LevelEnum)
+ }
+}
+
+impl Serialize for LevelFilter {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ match *self {
+ LevelFilter::Off => serializer.serialize_unit_variant("LevelFilter", 0, "OFF"),
+ LevelFilter::Error => serializer.serialize_unit_variant("LevelFilter", 1, "ERROR"),
+ LevelFilter::Warn => serializer.serialize_unit_variant("LevelFilter", 2, "WARN"),
+ LevelFilter::Info => serializer.serialize_unit_variant("LevelFilter", 3, "INFO"),
+ LevelFilter::Debug => serializer.serialize_unit_variant("LevelFilter", 4, "DEBUG"),
+ LevelFilter::Trace => serializer.serialize_unit_variant("LevelFilter", 5, "TRACE"),
+ }
+ }
+}
+
+impl<'de> Deserialize<'de> for LevelFilter {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ struct LevelFilterIdentifier;
+
+ impl<'de> Visitor<'de> for LevelFilterIdentifier {
+ type Value = LevelFilter;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("log level filter")
+ }
+
+ fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ // Case insensitive.
+ FromStr::from_str(s).map_err(|_| Error::unknown_variant(s, &LOG_LEVEL_NAMES))
+ }
+ }
+
+ impl<'de> DeserializeSeed<'de> for LevelFilterIdentifier {
+ type Value = LevelFilter;
+
+ fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ deserializer.deserialize_identifier(LevelFilterIdentifier)
+ }
+ }
+
+ struct LevelFilterEnum;
+
+ impl<'de> Visitor<'de> for LevelFilterEnum {
+ type Value = LevelFilter;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("log level filter")
+ }
+
+ fn visit_enum<A>(self, value: A) -> Result<Self::Value, A::Error>
+ where
+ A: EnumAccess<'de>,
+ {
+ let (level_filter, variant) = value.variant_seed(LevelFilterIdentifier)?;
+ // Every variant is a unit variant.
+ variant.unit_variant()?;
+ Ok(level_filter)
+ }
+ }
+
+ deserializer.deserialize_enum("LevelFilter", &LOG_LEVEL_NAMES, LevelFilterEnum)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ extern crate serde_test;
+ use self::serde_test::{Token, assert_tokens, assert_de_tokens, assert_de_tokens_error};
+
+ use {Level, LevelFilter};
+
+ fn level_token(variant: &'static str) -> Token {
+ Token::UnitVariant {
+ name: "Level",
+ variant: variant,
+ }
+ }
+
+ fn level_filter_token(variant: &'static str) -> Token {
+ Token::UnitVariant {
+ name: "LevelFilter",
+ variant: variant,
+ }
+ }
+
+ #[test]
+ fn test_level_ser_de() {
+ let cases = [
+ (Level::Error, [level_token("ERROR")]),
+ (Level::Warn, [level_token("WARN")]),
+ (Level::Info, [level_token("INFO")]),
+ (Level::Debug, [level_token("DEBUG")]),
+ (Level::Trace, [level_token("TRACE")]),
+ ];
+
+ for &(s, expected) in &cases {
+ assert_tokens(&s, &expected);
+ }
+ }
+
+ #[test]
+ fn test_level_case_insensitive() {
+ let cases = [
+ (Level::Error, [level_token("error")]),
+ (Level::Warn, [level_token("warn")]),
+ (Level::Info, [level_token("info")]),
+ (Level::Debug, [level_token("debug")]),
+ (Level::Trace, [level_token("trace")]),
+ ];
+
+ for &(s, expected) in &cases {
+ assert_de_tokens(&s, &expected);
+ }
+ }
+
+ #[test]
+ fn test_level_de_error() {
+ let msg = "unknown variant `errorx`, expected one of \
+ `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`";
+ assert_de_tokens_error::<Level>(&[level_token("errorx")], msg);
+ }
+
+ #[test]
+ fn test_level_filter_ser_de() {
+ let cases = [
+ (LevelFilter::Off, [level_filter_token("OFF")]),
+ (LevelFilter::Error, [level_filter_token("ERROR")]),
+ (LevelFilter::Warn, [level_filter_token("WARN")]),
+ (LevelFilter::Info, [level_filter_token("INFO")]),
+ (LevelFilter::Debug, [level_filter_token("DEBUG")]),
+ (LevelFilter::Trace, [level_filter_token("TRACE")]),
+ ];
+
+ for &(s, expected) in &cases {
+ assert_tokens(&s, &expected);
+ }
+ }
+
+ #[test]
+ fn test_level_filter_case_insensitive() {
+ let cases = [
+ (LevelFilter::Off, [level_filter_token("off")]),
+ (LevelFilter::Error, [level_filter_token("error")]),
+ (LevelFilter::Warn, [level_filter_token("warn")]),
+ (LevelFilter::Info, [level_filter_token("info")]),
+ (LevelFilter::Debug, [level_filter_token("debug")]),
+ (LevelFilter::Trace, [level_filter_token("trace")]),
+ ];
+
+ for &(s, expected) in &cases {
+ assert_de_tokens(&s, &expected);
+ }
+ }
+
+ #[test]
+ fn test_level_filter_de_error() {
+ let msg = "unknown variant `errorx`, expected one of \
+ `OFF`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`";
+ assert_de_tokens_error::<LevelFilter>(&[level_filter_token("errorx")], msg);
+ }
+}
--- a/third_party/rust/log/tests/filters.rs
+++ b/third_party/rust/log/tests/filters.rs
@@ -1,76 +1,66 @@
-#[macro_use] extern crate log;
+#[macro_use]
+extern crate log;
use std::sync::{Arc, Mutex};
-use log::{LogLevel, LogLevelFilter, Log, LogRecord, LogMetadata};
-use log::MaxLogLevelFilter;
+use log::{Level, LevelFilter, Log, Record, Metadata};
-#[cfg(feature = "use_std")]
-use log::set_logger;
-#[cfg(not(feature = "use_std"))]
-fn set_logger<M>(make_logger: M) -> Result<(), log::SetLoggerError>
- where M: FnOnce(MaxLogLevelFilter) -> Box<Log> {
- unsafe {
- log::set_logger_raw(|x| std::mem::transmute(make_logger(x)))
- }
+#[cfg(feature = "std")]
+use log::set_boxed_logger;
+
+#[cfg(not(feature = "std"))]
+fn set_boxed_logger(logger: Box<Log>) -> Result<(), log::SetLoggerError> {
+ log::set_logger(unsafe { &*Box::into_raw(logger) })
}
struct State {
- last_log: Mutex<Option<LogLevel>>,
- filter: MaxLogLevelFilter,
+ last_log: Mutex<Option<Level>>,
}
struct Logger(Arc<State>);
impl Log for Logger {
- fn enabled(&self, _: &LogMetadata) -> bool {
+ fn enabled(&self, _: &Metadata) -> bool {
true
}
- fn log(&self, record: &LogRecord) {
+ fn log(&self, record: &Record) {
*self.0.last_log.lock().unwrap() = Some(record.level());
}
+ fn flush(&self) {}
}
fn main() {
- let mut a = None;
- set_logger(|max| {
- let me = Arc::new(State {
- last_log: Mutex::new(None),
- filter: max,
- });
- a = Some(me.clone());
- Box::new(Logger(me))
- }).unwrap();
- let a = a.unwrap();
+ let me = Arc::new(State { last_log: Mutex::new(None) });
+ let a = me.clone();
+ set_boxed_logger(Box::new(Logger(me))).unwrap();
- test(&a, LogLevelFilter::Off);
- test(&a, LogLevelFilter::Error);
- test(&a, LogLevelFilter::Warn);
- test(&a, LogLevelFilter::Info);
- test(&a, LogLevelFilter::Debug);
- test(&a, LogLevelFilter::Trace);
+ test(&a, LevelFilter::Off);
+ test(&a, LevelFilter::Error);
+ test(&a, LevelFilter::Warn);
+ test(&a, LevelFilter::Info);
+ test(&a, LevelFilter::Debug);
+ test(&a, LevelFilter::Trace);
}
-fn test(a: &State, filter: LogLevelFilter) {
- a.filter.set(filter);
+fn test(a: &State, filter: LevelFilter) {
+ log::set_max_level(filter);
error!("");
- last(&a, t(LogLevel::Error, filter));
+ last(&a, t(Level::Error, filter));
warn!("");
- last(&a, t(LogLevel::Warn, filter));
+ last(&a, t(Level::Warn, filter));
info!("");
- last(&a, t(LogLevel::Info, filter));
+ last(&a, t(Level::Info, filter));
debug!("");
- last(&a, t(LogLevel::Debug, filter));
+ last(&a, t(Level::Debug, filter));
trace!("");
- last(&a, t(LogLevel::Trace, filter));
+ last(&a, t(Level::Trace, filter));
- fn t(lvl: LogLevel, filter: LogLevelFilter) -> Option<LogLevel> {
- if lvl <= filter {Some(lvl)} else {None}
+ fn t(lvl: Level, filter: LevelFilter) -> Option<Level> {
+ if lvl <= filter { Some(lvl) } else { None }
}
}
-fn last(state: &State, expected: Option<LogLevel>) {
- let mut lvl = state.last_log.lock().unwrap();
- assert_eq!(*lvl, expected);
- *lvl = None;
+fn last(state: &State, expected: Option<Level>) {
+ let lvl = state.last_log.lock().unwrap().take();
+ assert_eq!(lvl, expected);
}
--- a/toolkit/library/gtest/rust/Cargo.lock
+++ b/toolkit/library/gtest/rust/Cargo.lock
@@ -122,17 +122,17 @@ dependencies = [
]
[[package]]
name = "bindgen"
version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"clang-sys 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -183,17 +183,17 @@ name = "cexpr"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cfg-if"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clang-sys"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -257,17 +257,17 @@ dependencies = [
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "core-text"
-version = "9.0.0"
+version = "9.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -440,17 +440,17 @@ dependencies = [
"nsstring 0.1.0",
]
[[package]]
name = "encoding_rs"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"simd 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "env_logger"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
@@ -750,16 +750,24 @@ dependencies = [
]
[[package]]
name = "log"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "log"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "malloc_size_of"
version = "0.0.1"
dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hashglobe 0.1.0",
"ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -872,17 +880,17 @@ name = "mp4parse_fallible"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "net2"
version = "0.2.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "netwerk_helper"
@@ -1280,17 +1288,17 @@ name = "style"
version = "0.0.1"
dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bindgen 0.32.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
"debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fallible 0.0.1",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"hashglobe 0.1.0",
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1564,24 +1572,24 @@ name = "webrender"
version = "0.57.0"
dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-text 9.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core-text 9.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dwrote 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"freetype 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
"plane-split 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1611,17 +1619,17 @@ version = "0.1.0"
dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dwrote 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender 0.57.0",
]
[[package]]
name = "which"
version = "1.0.3"
@@ -1699,25 +1707,25 @@ dependencies = [
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5cde24d1b2e2216a726368b2363a273739c91f4e3eb4e0dd12d672d396ad989"
"checksum bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80b13e2ab064ff3aa0bdbf1eff533f9822dc37899821f5f98c67f263eab51707"
"checksum boxfnonce 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8380105befe91099e6f69206164072c05bc92427ff6aa8a5171388317346dd75"
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
"checksum bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d828f97b58cc5de3e40c421d0cf2132d6b2da4ee0e11b8632fa838f0f9333ad6"
"checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
-"checksum cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c47d456a36ebf0536a6705c83c1cbbcb9255fbc1d905a6ded104f479268a29"
+"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum clang-sys 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00048189ee171715296dfe3b2fcfd439563c7bfec0d98d3976ce3402d62c8f07"
"checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f"
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980"
"checksum core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41115a6aa5d3e1e5ef98148373f25971d1fad53818553f216495f9e67e90a624"
"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa"
"checksum core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb0ed45fdc32f9ab426238fba9407dfead7bacd7900c9b4dd3f396f46eafdae3"
-"checksum core-text 9.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c737a5c1f112943c961ed270aea64f7d0b01b425d327b040fa32b155646e07f"
+"checksum core-text 9.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd581c37283d0c23311d179aefbb891f2324ee0405da58a26e8594ab76e5748"
"checksum cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"
"checksum cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"
"checksum cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a807ac3ab7a217829c2a3b65732b926b2befe6a35f33b4bf8b503692430f223"
"checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
"checksum darling 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9861a8495606435477df581bc858ccf15a3469747edf175b94a4704fd9aaedac"
"checksum darling_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1486a8b00b45062c997f767738178b43219133dd0c8c826cb811e60563810821"
"checksum darling_macro 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a86ec160aa0c3dd492dd4a14ec8104ad8f1a9400a820624db857998cc1f80f9"
"checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
@@ -1752,16 +1760,17 @@ dependencies = [
"checksum khronos_api 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d867c645cfeb8a7fec503731679eac03ac11b7105aa5a71cb8f8ee5271636add"
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
"checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b"
"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2"
"checksum libloading 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "be99f814beb3e9503a786a592c909692bb6d4fc5a695f6ed7987223acfbd5194"
"checksum libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea626d3bdf40a1c5aee3bcd4f40826970cae8d80a8fec934c82a63840094dcfe"
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
+"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
"checksum memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46f3c7359028b31999287dae4e5047ddfe90a23b7dca2282ce759b491080c99b"
"checksum mio 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9e965267d4d58496fc4f740e9861118367f13570cadf66316ed2c3f2f14d87c7"
"checksum mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1731a873077147b626d89cc6c2a0db6288d607496c5d10c0cfcf3adc697ec673"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum moz_cbor 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f0dc96d1e40041ad9e6f9986e72e65d45d70dc31cef9d852b47646b2970f238"
"checksum mp4parse_fallible 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6626c2aef76eb8f984eef02e475883d3fe9112e114720446c5810fc5f045cd30"
--- a/toolkit/library/rust/Cargo.lock
+++ b/toolkit/library/rust/Cargo.lock
@@ -122,17 +122,17 @@ dependencies = [
]
[[package]]
name = "bindgen"
version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"clang-sys 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -183,17 +183,17 @@ name = "cexpr"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cfg-if"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clang-sys"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -257,17 +257,17 @@ dependencies = [
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "core-text"
-version = "9.0.0"
+version = "9.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -440,17 +440,17 @@ dependencies = [
"nsstring 0.1.0",
]
[[package]]
name = "encoding_rs"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"simd 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "env_logger"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
@@ -748,16 +748,24 @@ dependencies = [
]
[[package]]
name = "log"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "log"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "malloc_size_of"
version = "0.0.1"
dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hashglobe 0.1.0",
"ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -866,17 +874,17 @@ name = "mp4parse_fallible"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "net2"
version = "0.2.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "netwerk_helper"
@@ -1271,17 +1279,17 @@ name = "style"
version = "0.0.1"
dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bindgen 0.32.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
"debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fallible 0.0.1",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"hashglobe 0.1.0",
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1575,24 +1583,24 @@ name = "webrender"
version = "0.57.0"
dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-text 9.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "core-text 9.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dwrote 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"freetype 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
"plane-split 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1622,17 +1630,17 @@ version = "0.1.0"
dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dwrote 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender 0.57.0",
]
[[package]]
name = "which"
version = "1.0.3"
@@ -1701,25 +1709,25 @@ dependencies = [
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5cde24d1b2e2216a726368b2363a273739c91f4e3eb4e0dd12d672d396ad989"
"checksum bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80b13e2ab064ff3aa0bdbf1eff533f9822dc37899821f5f98c67f263eab51707"
"checksum boxfnonce 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8380105befe91099e6f69206164072c05bc92427ff6aa8a5171388317346dd75"
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
"checksum bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d828f97b58cc5de3e40c421d0cf2132d6b2da4ee0e11b8632fa838f0f9333ad6"
"checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
-"checksum cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c47d456a36ebf0536a6705c83c1cbbcb9255fbc1d905a6ded104f479268a29"
+"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum clang-sys 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00048189ee171715296dfe3b2fcfd439563c7bfec0d98d3976ce3402d62c8f07"
"checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f"
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980"
"checksum core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41115a6aa5d3e1e5ef98148373f25971d1fad53818553f216495f9e67e90a624"
"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa"
"checksum core-graphics 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb0ed45fdc32f9ab426238fba9407dfead7bacd7900c9b4dd3f396f46eafdae3"
-"checksum core-text 9.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c737a5c1f112943c961ed270aea64f7d0b01b425d327b040fa32b155646e07f"
+"checksum core-text 9.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd581c37283d0c23311d179aefbb891f2324ee0405da58a26e8594ab76e5748"
"checksum cose 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"
"checksum cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"
"checksum cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a807ac3ab7a217829c2a3b65732b926b2befe6a35f33b4bf8b503692430f223"
"checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
"checksum darling 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9861a8495606435477df581bc858ccf15a3469747edf175b94a4704fd9aaedac"
"checksum darling_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1486a8b00b45062c997f767738178b43219133dd0c8c826cb811e60563810821"
"checksum darling_macro 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a86ec160aa0c3dd492dd4a14ec8104ad8f1a9400a820624db857998cc1f80f9"
"checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
@@ -1754,16 +1762,17 @@ dependencies = [
"checksum khronos_api 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d867c645cfeb8a7fec503731679eac03ac11b7105aa5a71cb8f8ee5271636add"
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
"checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b"
"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2"
"checksum libloading 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "be99f814beb3e9503a786a592c909692bb6d4fc5a695f6ed7987223acfbd5194"
"checksum libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea626d3bdf40a1c5aee3bcd4f40826970cae8d80a8fec934c82a63840094dcfe"
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
+"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
"checksum memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46f3c7359028b31999287dae4e5047ddfe90a23b7dca2282ce759b491080c99b"
"checksum mio 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9e965267d4d58496fc4f740e9861118367f13570cadf66316ed2c3f2f14d87c7"
"checksum mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1731a873077147b626d89cc6c2a0db6288d607496c5d10c0cfcf3adc697ec673"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum moz_cbor 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f0dc96d1e40041ad9e6f9986e72e65d45d70dc31cef9d852b47646b2970f238"
"checksum mp4parse_fallible 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6626c2aef76eb8f984eef02e475883d3fe9112e114720446c5810fc5f045cd30"