Bug 1575883 - mach vendor rust. r=kinetik
authorPaul Adenot <paul@paul.cx>
Fri, 11 Oct 2019 16:02:18 +0000
changeset 562063 7c439c434ff50e80fadd3a3b2b7f588f7ba91b18
parent 562062 685d0c69909f9f46997b2b09152be7dc00835885
child 562064 ec7e9fc63c07c8dae8c6899cb4531b9b3e8e0469
push id2195
push userffxbld-merge
push dateMon, 25 Nov 2019 12:02:33 +0000
treeherdermozilla-release@19adee6f7bb3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik
bugs1575883
milestone71.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1575883 - mach vendor rust. r=kinetik Differential Revision: https://phabricator.services.mozilla.com/D47282
Cargo.lock
third_party/rust/audio_thread_priority/.cargo-checksum.json
third_party/rust/audio_thread_priority/Cargo.toml
third_party/rust/audio_thread_priority/Makefile
third_party/rust/audio_thread_priority/atp_test.cpp
third_party/rust/audio_thread_priority/audio_thread_priority.h
third_party/rust/audio_thread_priority/src/lib.rs
third_party/rust/audio_thread_priority/src/rt_linux.rs
third_party/rust/bitflags/.cargo-checksum.json
third_party/rust/bitflags/CHANGELOG.md
third_party/rust/bitflags/CODE_OF_CONDUCT.md
third_party/rust/bitflags/Cargo.toml
third_party/rust/bitflags/LICENSE-APACHE
third_party/rust/bitflags/LICENSE-MIT
third_party/rust/bitflags/README.md
third_party/rust/bitflags/build.rs
third_party/rust/bitflags/src/example_generated.rs
third_party/rust/bitflags/src/lib.rs
third_party/rust/cubeb-backend/.cargo-checksum.json
third_party/rust/cubeb-backend/Cargo.toml
third_party/rust/cubeb-backend/src/capi.rs
third_party/rust/cubeb-backend/src/ops.rs
third_party/rust/cubeb-backend/src/traits.rs
third_party/rust/cubeb-backend/tests/test_capi.rs
third_party/rust/cubeb-core/.cargo-checksum.json
third_party/rust/cubeb-core/Cargo.toml
third_party/rust/cubeb-core/src/stream.rs
third_party/rust/cubeb-sys/.cargo-checksum.json
third_party/rust/cubeb-sys/Cargo.toml
third_party/rust/cubeb-sys/build.rs
third_party/rust/cubeb-sys/libcubeb/CMakeLists.txt
third_party/rust/cubeb-sys/libcubeb/include/cubeb/cubeb.h
third_party/rust/cubeb-sys/libcubeb/src/cubeb-internal.h
third_party/rust/cubeb-sys/libcubeb/src/cubeb.c
third_party/rust/cubeb-sys/libcubeb/src/cubeb_alsa.c
third_party/rust/cubeb-sys/libcubeb/src/cubeb_audiotrack.c
third_party/rust/cubeb-sys/libcubeb/src/cubeb_audiounit.cpp
third_party/rust/cubeb-sys/libcubeb/src/cubeb_jack.cpp
third_party/rust/cubeb-sys/libcubeb/src/cubeb_kai.c
third_party/rust/cubeb-sys/libcubeb/src/cubeb_opensl.c
third_party/rust/cubeb-sys/libcubeb/src/cubeb_panner.cpp
third_party/rust/cubeb-sys/libcubeb/src/cubeb_panner.h
third_party/rust/cubeb-sys/libcubeb/src/cubeb_pulse.c
third_party/rust/cubeb-sys/libcubeb/src/cubeb_sndio.c
third_party/rust/cubeb-sys/libcubeb/src/cubeb_sun.c
third_party/rust/cubeb-sys/libcubeb/src/cubeb_wasapi.cpp
third_party/rust/cubeb-sys/libcubeb/src/cubeb_winmm.c
third_party/rust/cubeb-sys/libcubeb/test/test_audio.cpp
third_party/rust/cubeb-sys/libcubeb/test/test_sanity.cpp
third_party/rust/cubeb-sys/libcubeb/tools/cubeb-test.cpp
third_party/rust/cubeb-sys/src/lib.rs
third_party/rust/cubeb-sys/src/panner.rs
third_party/rust/cubeb-sys/src/stream.rs
third_party/rust/cubeb/.cargo-checksum.json
third_party/rust/cubeb/Cargo.toml
third_party/rust/scoped-tls-0.1.0/.cargo-checksum.json
third_party/rust/scoped-tls-0.1.0/Cargo.toml
third_party/rust/scoped-tls-0.1.0/LICENSE-APACHE
third_party/rust/scoped-tls-0.1.0/LICENSE-MIT
third_party/rust/scoped-tls-0.1.0/README.md
third_party/rust/scoped-tls-0.1.0/appveyor.yml
third_party/rust/scoped-tls-0.1.0/src/lib.rs
third_party/rust/semver-0.7.0/.cargo-checksum.json
third_party/rust/semver-0.7.0/Cargo.toml
third_party/rust/semver-0.7.0/LICENSE-APACHE
third_party/rust/semver-0.7.0/LICENSE-MIT
third_party/rust/semver-0.7.0/README.md
third_party/rust/semver-0.7.0/src/lib.rs
third_party/rust/semver-0.7.0/src/version.rs
third_party/rust/semver-0.7.0/src/version_req.rs
third_party/rust/semver-0.7.0/tests/deprecation.rs
third_party/rust/semver-0.7.0/tests/regression.rs
third_party/rust/semver-0.7.0/tests/serde.rs
third_party/rust/slab-0.3.0/.cargo-checksum.json
third_party/rust/slab-0.3.0/Cargo.toml
third_party/rust/slab-0.3.0/README.md
third_party/rust/slab-0.3.0/src/lib.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -69,89 +69,89 @@ source = "registry+https://github.com/ru
 dependencies = [
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
 name = "audio_thread_priority"
-version = "0.19.1"
+version = "0.20.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "dbus 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "mach 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
 name = "audioipc"
 version = "0.2.4"
 dependencies = [
+ "audio_thread_priority 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "cubeb 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cubeb 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio-named-pipes 0.1.6 (git+https://github.com/alexcrichton/mio-named-pipes)",
  "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-named-pipes 0.2.0 (git+https://github.com/NikVolf/tokio-named-pipes?branch=stable)",
  "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
 name = "audioipc-client"
 version = "0.4.0"
 dependencies = [
- "audio_thread_priority 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "audio_thread_priority 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "audioipc 0.2.4",
- "cubeb-backend 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cubeb-backend 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "audioipc-server"
 version = "0.2.3"
 dependencies = [
- "audio_thread_priority 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "audio_thread_priority 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "audioipc 0.2.4",
- "cubeb-core 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cubeb-core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "authenticator"
 version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "boxfnonce 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "devd-rs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -239,17 +239,17 @@ dependencies = [
  "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bindgen"
 version = "0.51.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cexpr 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -275,17 +275,17 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "bit_reverse"
 version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "bitflags"
-version = "1.0.4"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "bitreader"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -465,30 +465,30 @@ dependencies = [
 
 [[package]]
 name = "clap"
 version = "2.31.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cloudabi"
 version = "0.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cmake"
 version = "0.1.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -531,17 +531,17 @@ name = "core-foundation-sys"
 version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "core-graphics"
 version = "0.17.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.3 (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.60 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "core-text"
 version = "13.0.0"
@@ -744,67 +744,67 @@ version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cubeb"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cubeb-core 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cubeb-core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cubeb-backend"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cubeb-core 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cubeb-core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cubeb-core"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "cubeb-sys 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cubeb-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cubeb-coreaudio"
 version = "0.1.0"
 dependencies = [
  "atomic 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "coreaudio-sys-utils 0.1.0",
- "cubeb-backend 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cubeb-backend 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "mach 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cubeb-pulse"
-version = "0.2.0"
-dependencies = [
- "cubeb-backend 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "pulse 0.2.0",
+version = "0.3.0"
+dependencies = [
+ "cubeb-backend 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pulse 0.3.0",
  "pulse-ffi 0.1.0",
  "ringbuf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cubeb-sys"
-version = "0.5.5"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "darling"
@@ -1094,17 +1094,17 @@ name = "fuchsia-cprng"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "fuchsia-zircon"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "fuchsia-zircon-sys"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -1214,27 +1214,27 @@ dependencies = [
  "xpcom-gtest 0.1.0",
 ]
 
 [[package]]
 name = "gkrust-shared"
 version = "0.1.0"
 dependencies = [
  "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "audio_thread_priority 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "audio_thread_priority 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "audioipc-client 0.4.0",
  "audioipc-server 0.2.3",
  "authenticator 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitsdownload 0.1.0",
  "bookmark_sync 0.1.0",
  "cert_storage 0.0.1",
  "cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "cubeb-coreaudio 0.1.0",
- "cubeb-pulse 0.2.0",
- "cubeb-sys 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cubeb-pulse 0.3.0",
+ "cubeb-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding_glue 0.1.0",
  "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "geckoservo 0.0.1",
  "gkrust_utils 0.1.0",
  "jsrust_shared 0.1.0",
  "kvstore 0.1.0",
  "lmdb-rkv-sys 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1331,17 +1331,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "headers"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "headers-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "headers-derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1617,17 +1617,17 @@ name = "linked-hash-map"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "lmdb-rkv"
 version = "0.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "lmdb-rkv-sys 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "lmdb-rkv-sys"
 version = "0.9.5"
@@ -2012,17 +2012,17 @@ version = "0.1.0"
 dependencies = [
  "nsstring 0.1.0",
 ]
 
 [[package]]
 name = "nsstring"
 version = "0.1.0"
 dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "nsstring-gtest"
 version = "0.1.0"
 dependencies = [
  "nsstring 0.1.0",
@@ -2238,17 +2238,17 @@ dependencies = [
  "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "png"
 version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "podio"
 version = "0.1.5"
@@ -2293,19 +2293,19 @@ dependencies = [
  "object 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "thin-vec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "pulse"
-version = "0.2.0"
-dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+version = "0.3.0"
+dependencies = [
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulse-ffi 0.1.0",
 ]
 
 [[package]]
 name = "pulse-ffi"
 version = "0.1.0"
 dependencies = [
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2517,17 +2517,17 @@ dependencies = [
 
 [[package]]
 name = "rkv"
 version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lmdb-rkv 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2621,21 +2621,16 @@ name = "same-file"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
 name = "scoped-tls"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "scoped-tls"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "scopeguard"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -2657,17 +2652,17 @@ dependencies = [
  "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "selectors"
 version = "0.21.0"
 dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.25.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2683,16 +2678,24 @@ name = "semver"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "semver"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver"
 version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "semver-parser"
@@ -2826,21 +2829,16 @@ version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "size_of_test"
 version = "0.0.1"
 
 [[package]]
 name = "slab"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "slab"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "smallbitvec"
 version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -2906,17 +2904,17 @@ source = "registry+https://github.com/ru
 [[package]]
 name = "style"
 version = "0.0.1"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "arrayvec 0.4.11 (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.51.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.25.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fallible 0.0.1",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2970,17 +2968,17 @@ dependencies = [
  "synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "style_traits"
 version = "0.0.1"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.25.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.21.0",
  "servo_arc 0.1.1",
  "to_shmem 0.0.1",
@@ -3533,17 +3531,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "webrender"
 version = "0.60.0"
 dependencies = [
  "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3572,17 +3570,17 @@ dependencies = [
  "ws 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webrender_api"
 version = "0.60.0"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "peek-poke 0.2.0",
  "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3808,29 +3806,29 @@ dependencies = [
 "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
 "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 "checksum app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9dadc668390b373e73e4abbfc1f07238b09a25858f2f39c06cebc6d8e141d774"
 "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
 "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
 "checksum atomic 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c210c1f4db048cda477b652d170572d84c9640695835f17663595d3bd543fc28"
 "checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21"
 "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
-"checksum audio_thread_priority 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c1e4aab7f57d8334168073cd0d0f11c7d1f7f3aabef84a1733a42629d0da80c"
+"checksum audio_thread_priority 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)" = "197b2d259505d11c92d266e1784f01cc935eb764d2f54e16aedf4e5085197871"
 "checksum authenticator 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ec149e5d5d4caa2c9ead53a8ce1ea9c4204c388c65bf3b96c2d1dc0fcf4aeb66"
 "checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
 "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
 "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
 "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
 "checksum binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff"
 "checksum bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bda13183df33055cbb84b847becce220d392df502ebe7a4a78d7021771ed94d0"
 "checksum bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebd71393f1ec0509b553aa012b9b58e81dadbdff7130bd3b8cba576e69b32f75"
 "checksum binjs_meta 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c9a0da2208ceb785c1626fa8b7d250d2e5546ae230294b4a998e4f818c1768e"
 "checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"
 "checksum bit_reverse 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5e97e02db5a2899c0377f3d6031d5da8296ca2b47abef6ed699de51b9e40a28c"
-"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
+"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2"
 "checksum bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80b13e2ab064ff3aa0bdbf1eff533f9822dc37899821f5f98c67f263eab51707"
 "checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182"
 "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
 "checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3"
 "checksum boxfnonce 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8380105befe91099e6f69206164072c05bc92427ff6aa8a5171388317346dd75"
 "checksum byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182"
 "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
 "checksum bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e178b8e0e239e844b083d5a0d4a156b2654e67f9f80144d48398fcd736a24fb8"
@@ -3862,20 +3860,20 @@ dependencies = [
 "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
 "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
 "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
 "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
 "checksum cssparser 0.25.9 (registry+https://github.com/rust-lang/crates.io-index)" = "fbe18ca4efb9ba3716c6da66cc3d7e673bf59fa576353011f48c4cfddbdd740e"
 "checksum cssparser-macros 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5bb1c84e87c717666564ec056105052331431803d606bd45529b28547b611eef"
 "checksum cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b6557bdb1dc9647eae1cf7f5601b14cd45fc3c7ccf2df618387416fe542da6ea"
 "checksum cstr-macros 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "cd670e5ff58768ef624207fb95709ce63b8d05573fb9a05165f0eef471ea6a3a"
-"checksum cubeb 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "50f6a746cc3a80bdc96203e617d3bfc8988169c012c85c4ca4f1bad7862441bc"
-"checksum cubeb-backend 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "54c14a298d865c7f454dd809b2feb1fdb361b0a143f8ed2ea0b3a9becfa0a2ea"
-"checksum cubeb-core 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "20c6cde72d3505dc4f2452e0378b970b03d1fddf3ad8ac1b98dcb65fc7721907"
-"checksum cubeb-sys 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "318d9b60d6d5de52f815882ab5405adedc0ac7e91414950eff27a440c2860a3b"
+"checksum cubeb 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3cbcdfde9ea319160af6eff068ffaa96aad3532e1b5c0ebc134614cfacacae24"
+"checksum cubeb-backend 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5a1e7add4e7642a8aebb24172922318482bed52389a12cb339f728bbd4c4ed9c"
+"checksum cubeb-core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfd9b2ea1cb6afed9419b0d18fc4093df552ccb2300eb57793629f8cd370b4c8"
+"checksum cubeb-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "309c5839c5fa03c08363bd308566cbe4654b25a9984342d7546a33d55b80a3d6"
 "checksum darling 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe629a532efad5526454efb0700f86d5ad7ff001acb37e431c8bf017a432a8e"
 "checksum darling_core 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ee54512bec54b41cf2337a22ddfadb53c7d4c738494dc2a186d7b037ad683b85"
 "checksum darling_macro 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cd3e432e52c0810b72898296a69d66b1d78d1517dff6cde7a130557a55a62c1"
 "checksum dbus 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e1b39f3f6aa3d4a1522c4f0f9f1e9e9167bd93740a8690874caa7cf8ce47d7"
 "checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86"
 "checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871"
 "checksum devd-rs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d009f166c0d9e9f9909dc751630b3a6411ab7f85a153d32d01deb364ffe52a7"
 "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
@@ -4026,38 +4024,37 @@ dependencies = [
 "checksum rust-ini 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a654c5bda722c699be6b0fe4c0d90de218928da5b724c3e467fc48865c37263"
 "checksum rust_cascade 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f3fe4900d38dab1ad21a515e44687dd0711e6b0ec5b214a3b1aa8857343bcf3a"
 "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649"
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
 "checksum ryu 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0568787116e13c652377b6846f5931454a363a8fdf8ae50463ee40935b278b"
 "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9"
 "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
-"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
 "checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
 "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
 "checksum scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f84d114ef17fd144153d608fba7c446b0145d038985e7a8cc5d08bb0ce20383"
 "checksum scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1aa96c45e7f5a91cb7fabe7b279f02fea7126239fc40b732316e8b6a2d0fcb"
 "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
+"checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85"
 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 "checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850"
 "checksum serde_bytes 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "45af0182ff64abaeea290235eb67da3825a576c5d53e642c4d5b652e12e6effc"
 "checksum serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "beed18e6f5175aef3ba670e57c60ef3b1b74d250d962a26604bff4c80e970dd4"
 "checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae"
 "checksum serde_repr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "29a734c298df0346c4cd5919595981c266dabbf12dc747c85e1a95e96077a52b"
 "checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
 "checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582"
 "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68"
 "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
 "checksum shift_or_euc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f930dea4685b9803954b9d74cdc175c6d946a22f2eafe5aa2e9a58cdcae7da8c"
 "checksum shift_or_euc_c 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c81ec08c8a68c45c48d8ef58b80ce038cc9945891c4a4996761e2ec5cba05abc"
 "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
 "checksum siphasher 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ffc669b726f2bc9a3bcff66e5e23b56ba6bf70e22a34c3d7b6d0b3450b65b84"
-"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
 "checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d"
 "checksum smallbitvec 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1764fe2b30ee783bfe3b9b37b2649d8d590b3148bb12e0079715d4d5c673562e"
 "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
 "checksum socket2 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "df028e0e632c2a1823d920ad74895e7f9128e6438cbc4bc6fd1f180e644767b9"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
 "checksum string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00caf261d6f90f588f8450b8e1230fa0d5be49ee6140fdfbcb55335aff350970"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
 "checksum svg_fmt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c666f0fed8e1e20e057af770af9077d72f3d5a33157b8537c1475dd8ffd6d32b"
--- a/third_party/rust/audio_thread_priority/.cargo-checksum.json
+++ b/third_party/rust/audio_thread_priority/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"a18d74797e678c75ae36f85e15092ea4eca698f5e8a2580c3144e32f407164d4","README.md":"bcfa4948edf52fdacd485200a0c1c886a92232cc1931eeb4e1044050f46ec253","audio_thread_priority.h":"880889a154283a87cf84218cc4d6b2b9dd2c8fd09adc6d38f527b08ccd0c6168","generate_osx_bindings.sh":"06e4e03450f788ced18d31fff5660919e6f6ec1119ddace363ffeb82f0518a71","src/lib.rs":"25df84928756bc50fa908d65acace5259b59dfa5fc57a3f0f8b0e1f8a98ab512","src/mach_sys.rs":"352560fcb9b41d877cff92e5b3b04d6dc68b1f30508ce4b9aed78940120a883e","src/rt_linux.rs":"3da1550beacc8f8a0d86c07ed190ceef7d56398c675b99a145919f5c7231eed7","src/rt_mach.rs":"5fce324b9a64305ff221fdd185eaa4b1c7386b6e61edc32cf63e424f9f3d90ef","src/rt_win.rs":"f8f5b7af21cadd686cf7d8099d1972d3265c3889574020bd4ea088b832fbfa51"},"package":"4c1e4aab7f57d8334168073cd0d0f11c7d1f7f3aabef84a1733a42629d0da80c"}
\ No newline at end of file
+{"files":{"Cargo.toml":"363ab43ea4980149350eb3a4da691a93f0b7c61a5d3b4ce8b59f73cde5866a92","Makefile":"0f9a771cfb30c7c4b9961d82fdca4e9e229a955bb2e636474a4101389e18e938","README.md":"bcfa4948edf52fdacd485200a0c1c886a92232cc1931eeb4e1044050f46ec253","atp_test.cpp":"8075a040941a65fb9e3f7cbf0535853ca6661c3ac442ec35569b42b24bbec797","audio_thread_priority.h":"f0ecaf1b674f794cde0dc834028e074d4e4675d22ae96acf08b2ae1dceb3474e","generate_osx_bindings.sh":"06e4e03450f788ced18d31fff5660919e6f6ec1119ddace363ffeb82f0518a71","src/lib.rs":"516388cf4ccf55f23a6ccb248f56ab525b759a24819e67605cd12f640517ddd3","src/mach_sys.rs":"352560fcb9b41d877cff92e5b3b04d6dc68b1f30508ce4b9aed78940120a883e","src/rt_linux.rs":"b4db36baa754ab166b40f3801acc4f2046d226a2645f0e136dbbfa1bc771344e","src/rt_mach.rs":"5fce324b9a64305ff221fdd185eaa4b1c7386b6e61edc32cf63e424f9f3d90ef","src/rt_win.rs":"f8f5b7af21cadd686cf7d8099d1972d3265c3889574020bd4ea088b832fbfa51"},"package":"197b2d259505d11c92d266e1784f01cc935eb764d2f54e16aedf4e5085197871"}
\ No newline at end of file
--- a/third_party/rust/audio_thread_priority/Cargo.toml
+++ b/third_party/rust/audio_thread_priority/Cargo.toml
@@ -8,17 +8,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]
 edition = "2018"
 name = "audio_thread_priority"
-version = "0.19.1"
+version = "0.20.2"
 authors = ["Paul Adenot <paul@paul.cx>"]
 description = "Bump a thread to real-time priority, for audio work, on Linux, Windows and macOS"
 license = "MPL-2.0"
 repository = "https://github.com/padenot/audio_thread_priority"
 
 [lib]
 name = "audio_thread_priority"
 crate-type = ["staticlib", "rlib"]
@@ -26,16 +26,18 @@ crate-type = ["staticlib", "rlib"]
 version = "0.1"
 
 [dependencies.log]
 version = "0.4"
 
 [dependencies.simple_logger]
 version = "0.4"
 optional = true
+[dev-dependencies.nix]
+version = "0.15.0"
 
 [features]
 terminal-logging = ["simple_logger"]
 [target."cfg(target_os = \"linux\")".dependencies.dbus]
 version = "0.6.4"
 
 [target."cfg(target_os = \"linux\")".dependencies.libc]
 version = "0.2"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/audio_thread_priority/Makefile
@@ -0,0 +1,8 @@
+all: target/debug/libaudio_thread_priority.a
+	g++ atp_test.cpp target/debug/libaudio_thread_priority.a -I. -lpthread -ldbus-1 -ldl -g -o atp_test
+
+check:
+	@./atp_test && echo "test passed" || echo "test failed"
+
+target/debug/libaudio_thread_priority.a:
+	cargo build
new file mode 100644
--- /dev/null
+++ b/third_party/rust/audio_thread_priority/atp_test.cpp
@@ -0,0 +1,30 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "audio_thread_priority.h"
+
+int main() {
+#ifdef __linux__
+  atp_thread_info* info = atp_get_current_thread_info();
+  atp_thread_info* info2 = nullptr;
+
+  uint8_t buffer[ATP_THREAD_INFO_SIZE];
+  atp_serialize_thread_info(info, buffer);
+
+  info2 = atp_deserialize_thread_info(buffer);
+
+  int rv = memcmp(info, info2, ATP_THREAD_INFO_SIZE);
+
+  assert(!rv);
+
+  atp_free_thread_info(info);
+  atp_free_thread_info(info2);
+
+  rv = atp_set_real_time_limit(0, 44100);
+  assert(!rv);
+#endif
+
+  return 0;
+}
--- a/third_party/rust/audio_thread_priority/audio_thread_priority.h
+++ b/third_party/rust/audio_thread_priority/audio_thread_priority.h
@@ -8,16 +8,18 @@
 #include <stdint.h>
 #include <stdlib.h>
 
 /**
  * An opaque structure containing information about a thread that was promoted
  * to real-time priority.
  */
 struct atp_handle;
+struct atp_thread_info;
+extern size_t ATP_THREAD_INFO_SIZE;
 
 #ifdef __cplusplus
 extern "C" {
 #endif // __cplusplus
 
 /**
  * Promotes the current thread to real-time priority.
  *
@@ -26,16 +28,17 @@ extern "C" {
  * or an upper bound.
  * audio_samplerate_hz: sample-rate for this audio stream, in Hz
  *
  * Returns an opaque handle in case of success, NULL otherwise.
  */
 atp_handle *atp_promote_current_thread_to_real_time(uint32_t audio_buffer_frames,
                                                     uint32_t audio_samplerate_hz);
 
+
 /**
  * Demotes the current thread promoted to real-time priority via
  * `atp_demote_current_thread_from_real_time` to its previous priority.
  *
  * Returns 0 in case of success, non-zero otherwise.
  */
 int32_t atp_demote_current_thread_from_real_time(atp_handle *handle);
 
@@ -44,13 +47,107 @@ int32_t atp_demote_current_thread_from_r
  *`atp_demote_current_thread_from_real_time` on the right thread. Access to the
  * handle must be synchronized externaly (or the related thread must have
  * exited).
  *
  * Returns 0 in case of success, non-zero otherwise.
  */
 int32_t atp_free_handle(atp_handle *handle);
 
+/*
+ * Linux-only API.
+ *
+ * The Linux backend uses DBUS to promote a thread to real-time priority. In
+ * environment where this is not possible (due to sandboxing), this set of
+ * functions allow remoting the call to a process that can make DBUS calls.
+ *
+ * To do so:
+ * - Set the real-time limit from within the process where a
+ *   thread will be promoted. This is a `setrlimit` call, that can be done
+ *   before the sandbox lockdown.
+ * - Then, gather information on the thread that will be promoted.
+ * - Serialize this info.
+ * - Send over the serialized data via an IPC mechanism
+ * - Deserialize the inf
+ * - Call `atp_promote_thread_to_real_time`
+ */
+
+#ifdef __linux__
+/**
+ * Promotes a thread, possibly in another process, to real-time priority.
+ *
+ * thread_info: info on the thread to promote, gathered with
+ * `atp_get_current_thread_info()`, called on the thread itself.
+ * audio_buffer_frames: number of frames per audio buffer. If unknown, passing 0
+ * will choose an appropriate number, conservatively. If variable, either pass 0
+ * or an upper bound.
+ * audio_samplerate_hz: sample-rate for this audio stream, in Hz
+ *
+ * Returns an opaque handle in case of success, NULL otherwise.
+ *
+ * This call is useful on Linux desktop only, when the process is sandboxed and
+ * cannot promote itself directly.
+ */
+atp_handle *atp_promote_thread_to_real_time(atp_thread_info *thread_info);
+
+/**
+ * Demotes a thread promoted to real-time priority via
+ * `atp_demote_thread_from_real_time` to its previous priority.
+ *
+ * Returns 0 in case of success, non-zero otherwise.
+ *
+ * This call is useful on Linux desktop only, when the process is sandboxed and
+ * cannot promote itself directly.
+ */
+int32_t atp_demote_thread_from_real_time(atp_thread_info* thread_info);
+
+/**
+ * Gather informations from the calling thread, to be able to promote it from
+ * another thread and/or process.
+ *
+ * Returns a non-null pointer to an `atp_thread_info` structure in case of
+ * sucess, to be freed later with `atp_free_thread_info`, and NULL otherwise.
+ *
+ * This call is useful on Linux desktop only, when the process is sandboxed and
+ * cannot promote itself directly.
+ */
+atp_thread_info *atp_get_current_thread_info();
+
+/**
+ * Free an `atp_thread_info` structure.
+ *
+ * Returns 0 in case of success, non-zero in case of error (because thread_info
+ * was NULL).
+ */
+int32_t atp_free_thread_info(atp_thread_info *thread_info);
+
+/**
+ * Serialize an `atp_thread_info` to a byte buffer that is
+ * sizeof(atp_thread_info) long.
+ */
+void atp_serialize_thread_info(atp_thread_info *thread_info, uint8_t *bytes);
+
+/**
+ * Deserialize a byte buffer of sizeof(atp_thread_info) to an `atp_thread_info`
+ * pointer. It can be then freed using atp_free_thread_info.
+ * */
+atp_thread_info* atp_deserialize_thread_info(uint8_t *bytes);
+
+/**
+ * Set real-time limit for the calling process.
+ *
+ * This is useful only on Linux desktop, and allows remoting the rtkit DBUS call
+ * to a process that has access to DBUS. This function has to be called before
+ * attempting to promote threads from another process.
+ *
+ * This sets the real-time computation limit. For actually promoting the thread
+ * to a real-time scheduling class, see `atp_promote_thread_to_real_time`.
+ */
+int32_t atp_set_real_time_limit(uint32_t audio_buffer_frames,
+                                uint32_t audio_samplerate_hz);
+
+#endif // __linux__
+
 #ifdef __cplusplus
 } // extern "C"
 #endif // __cplusplus
 
 #endif // AUDIO_THREAD_PRIORITY_H
--- a/third_party/rust/audio_thread_priority/src/lib.rs
+++ b/third_party/rust/audio_thread_priority/src/lib.rs
@@ -1,19 +1,22 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#[warn(missing_docs)]
+
 #[macro_use]
 extern crate cfg_if;
 #[cfg(feature = "terminal-logging")]
 extern crate simple_logger;
 #[macro_use]
 extern crate log;
 
+
 cfg_if! {
     if #[cfg(target_os = "macos")] {
         mod rt_mach;
 #[allow(unused, non_camel_case_types, non_snake_case, non_upper_case_globals)]
         mod mach_sys;
         extern crate mach;
         extern crate libc;
         use rt_mach::promote_current_thread_to_real_time_internal;
@@ -24,38 +27,298 @@ cfg_if! {
         mod rt_win;
         use rt_win::promote_current_thread_to_real_time_internal;
         use rt_win::demote_current_thread_from_real_time_internal;
         use rt_win::RtPriorityHandleInternal;
     } else if #[cfg(target_os = "linux")] {
         mod rt_linux;
         extern crate dbus;
         extern crate libc;
+        use rt_linux::set_real_time_hard_limit_internal as set_real_time_hard_limit;
         use rt_linux::promote_current_thread_to_real_time_internal;
         use rt_linux::demote_current_thread_from_real_time_internal;
+        use rt_linux::get_current_thread_info_internal;
+        use rt_linux::promote_thread_to_real_time_internal;
+        use rt_linux::demote_thread_from_real_time_internal;
+        use rt_linux::RtPriorityThreadInfoInternal;
         use rt_linux::RtPriorityHandleInternal;
+        #[no_mangle]
+        /// Size of a RtPriorityThreadInfo or atp_thread_info struct, for use in FFI.
+        pub static ATP_THREAD_INFO_SIZE: usize = std::mem::size_of::<RtPriorityThreadInfo>();
     } else {
+        // blanket implementations for Android and other systems.
         pub struct RtPriorityHandleInternal {}
         pub fn promote_current_thread_to_real_time_internal(_: u32, audio_samplerate_hz: u32) -> Result<RtPriorityHandle, ()> {
             if audio_samplerate_hz == 0 {
                 return Err(());
             }
             // no-op
-            return Ok(RtPriorityHandle{});
+            Ok(RtPriorityHandle{})
         }
         pub fn demote_current_thread_from_real_time_internal(_: RtPriorityHandle) -> Result<(), ()> {
             // no-op
-            return Ok(());
+            Ok(())
         }
     }
 }
 
 /// Opaque handle to a thread handle structure.
 pub type RtPriorityHandle = RtPriorityHandleInternal;
 
+cfg_if! {
+    if #[cfg(target_os = "linux")] {
+/// Opaque handle to a thread info.
+///
+/// This can be serialized to raw bytes to be sent via IPC.
+///
+/// This call is useful on Linux desktop only, when the process is sandboxed and
+/// cannot promote itself directly.
+pub type RtPriorityThreadInfo = RtPriorityThreadInfoInternal;
+
+
+/// Get the calling thread's information, to be able to promote it to real-time from somewhere
+/// else, later.
+///
+/// This call is useful on Linux desktop only, when the process is sandboxed and
+/// cannot promote itself directly.
+///
+/// # Return value
+///
+/// Ok in case of success, with an opaque structure containing relevant info for the platform, Err
+/// otherwise.
+pub fn get_current_thread_info() -> Result<RtPriorityThreadInfo, ()> {
+    return get_current_thread_info_internal();
+}
+
+/// Return a byte buffer containing serialized information about a thread, to promote it to
+/// real-time from elsewhere.
+///
+/// This call is useful on Linux desktop only, when the process is sandboxed and
+/// cannot promote itself directly.
+pub fn thread_info_serialize(
+    thread_info: RtPriorityThreadInfo,
+) -> [u8; std::mem::size_of::<RtPriorityThreadInfo>()] {
+    return thread_info.serialize();
+}
+
+/// From a byte buffer, return a `RtPriorityThreadInfo`.
+///
+/// This call is useful on Linux desktop only, when the process is sandboxed and
+/// cannot promote itself directly.
+///
+/// # Arguments
+///
+/// A byte buffer containing a serializezd `RtPriorityThreadInfo`.
+pub fn thread_info_deserialize(
+    bytes: [u8; std::mem::size_of::<RtPriorityThreadInfo>()],
+) -> RtPriorityThreadInfo {
+    return RtPriorityThreadInfoInternal::deserialize(bytes);
+}
+
+/// Get the calling threads' information, to promote it from another process or thread, with a C
+/// API.
+///
+/// This is intended to call on the thread that will end up being promoted to real time priority,
+/// but that cannot do it itself (probably because of sandboxing reasons).
+///
+/// After use, it MUST be freed by calling `atp_free_thread_info`.
+///
+/// # Return value
+///
+/// A pointer to a struct that can be serialized and deserialized, and that can be passed to
+/// `atp_promote_thread_to_real_time`, even from another process.
+#[no_mangle]
+pub extern "C" fn atp_get_current_thread_info() -> *mut atp_thread_info {
+    match get_current_thread_info() {
+        Ok(thread_info) => Box::into_raw(Box::new(atp_thread_info(thread_info))),
+        _ => std::ptr::null_mut(),
+    }
+}
+
+/// Frees a thread info, with a c api.
+///
+/// # Arguments
+///
+/// thread_info: the `atp_thread_info` structure to free.
+///
+/// # Return value
+///
+/// 0 in case of success, 1 otherwise (if `thread_info` is NULL).
+#[no_mangle]
+pub extern "C" fn atp_free_thread_info(thread_info: *mut atp_thread_info) -> i32 {
+    if thread_info.is_null() {
+        return 1;
+    }
+    unsafe { Box::from_raw(thread_info) };
+    0
+}
+
+/// Return a byte buffer containing serialized information about a thread, to promote it to
+/// real-time from elsewhere, with a C API.
+///
+/// `bytes` MUST be `std::mem::size_of<RtPriorityThreadInfo>()` bytes long.
+///
+/// This is exposed in the C API as `ATP_THREAD_INFO_SIZE`.
+///
+/// This call is useful on Linux desktop only, when the process is sandboxed, cannot promote itself
+/// directly, and the `atp_thread_info` struct must be passed via IPC.
+#[no_mangle]
+pub extern "C" fn atp_serialize_thread_info(
+    thread_info: *mut atp_thread_info,
+    bytes: *mut libc::c_void,
+) {
+    let thread_info = unsafe { &mut *thread_info };
+    let source = thread_info.0.serialize();
+    unsafe {
+        std::ptr::copy(source.as_ptr(), bytes as *mut u8, source.len());
+    }
+}
+
+/// From a byte buffer, return a `RtPriorityThreadInfo`, with a C API.
+///
+/// This call is useful on Linux desktop only, when the process is sandboxed and
+/// cannot promote itself directly.
+///
+/// # Arguments
+///
+/// A byte buffer containing a serializezd `RtPriorityThreadInfo`.
+#[no_mangle]
+pub extern "C" fn atp_deserialize_thread_info(
+    in_bytes: *mut u8,
+) -> *mut atp_thread_info {
+    let bytes = unsafe { *(in_bytes as *mut [u8; std::mem::size_of::<RtPriorityThreadInfoInternal>()]) };
+    let thread_info = RtPriorityThreadInfoInternal::deserialize(bytes);
+    return Box::into_raw(Box::new(atp_thread_info(thread_info)));
+}
+
+/// Promote a particular thread thread to real-time priority.
+///
+/// This call is useful on Linux desktop only, when the process is sandboxed and
+/// cannot promote itself directly.
+///
+/// # Arguments
+///
+/// * `thread_info` - informations about the thread to promote, gathered using
+/// `get_current_thread_info`.
+/// * `audio_buffer_frames` - the exact or an upper limit on the number of frames that have to be
+/// rendered each callback, or 0 for a sensible default value.
+/// * `audio_samplerate_hz` - the sample-rate for this audio stream, in Hz.
+///
+/// # Return value
+///
+/// This function returns a `Result<RtPriorityHandle>`, which is an opaque struct to be passed to
+/// `demote_current_thread_from_real_time` to revert to the previous thread priority.
+pub fn promote_thread_to_real_time(
+    thread_info: RtPriorityThreadInfo,
+    audio_buffer_frames: u32,
+    audio_samplerate_hz: u32,
+) -> Result<RtPriorityHandle, ()> {
+    if audio_samplerate_hz == 0 {
+        return Err(());
+    }
+    return promote_thread_to_real_time_internal(
+        thread_info,
+        audio_buffer_frames,
+        audio_samplerate_hz,
+    );
+}
+
+/// Demotes a thread from real-time priority.
+///
+/// # Arguments
+///
+/// * `thread_info` - An opaque struct returned from a successful call to
+/// `get_current_thread_info`.
+///
+/// # Return value
+///
+/// `Ok` in case of success, `Err` otherwise.
+pub fn demote_thread_from_real_time(thread_info: RtPriorityThreadInfo) -> Result<(), ()> {
+    return demote_thread_from_real_time_internal(thread_info);
+}
+
+/// Opaque info to a particular thread.
+#[allow(non_camel_case_types)]
+pub struct atp_thread_info(RtPriorityThreadInfo);
+
+/// Promote a specific thread to real-time, with a C API.
+///
+/// This is useful when the thread to promote cannot make some system calls necessary to promote
+/// it.
+///
+/// # Arguments
+///
+/// `thread_info` - the information of the thread to promote to real-time, gather from calling
+/// `atp_get_current_thread_info` on the thread to promote.
+/// * `audio_buffer_frames` - the exact or an upper limit on the number of frames that have to be
+/// rendered each callback, or 0 for a sensible default value.
+/// * `audio_samplerate_hz` - the sample-rate for this audio stream, in Hz.
+///
+/// # Return value
+///
+/// A pointer to an `atp_handle` in case of success, NULL otherwise.
+#[no_mangle]
+pub extern "C" fn atp_promote_thread_to_real_time(
+    thread_info: *mut atp_thread_info,
+    audio_buffer_frames: u32,
+    audio_samplerate_hz: u32,
+) -> *mut atp_handle {
+    let thread_info = unsafe { &mut *thread_info };
+    match promote_thread_to_real_time(thread_info.0, audio_buffer_frames, audio_samplerate_hz) {
+        Ok(handle) => Box::into_raw(Box::new(atp_handle(handle))),
+        _ => std::ptr::null_mut(),
+    }
+}
+
+/// Demote a thread promoted to from real-time, with a C API.
+///
+/// # Arguments
+///
+/// `handle` -  an opaque struct received from a promoting function.
+///
+/// # Return value
+///
+/// 0 in case of success, non-zero otherwise.
+#[no_mangle]
+pub extern "C" fn atp_demote_thread_from_real_time(thread_info: *mut atp_thread_info) -> i32 {
+    if thread_info.is_null() {
+        return 1;
+    }
+    let thread_info = unsafe { (*thread_info).0 };
+
+    match demote_thread_from_real_time(thread_info) {
+        Ok(_) => 0,
+        _ => 1,
+    }
+}
+
+/// Set a real-time limit for the calling thread.
+///
+/// # Arguments
+///
+/// `audio_buffer_frames` - the number of frames the audio callback has to render each quantum. 0
+/// picks a rather high default value.
+/// `audio_samplerate_hz` - the sample-rate of the audio stream.
+///
+/// # Return value
+///
+/// 0 in case of success, 1 otherwise.
+#[no_mangle]
+pub extern "C" fn atp_set_real_time_limit(audio_buffer_frames: u32,
+                                          audio_samplerate_hz: u32) -> i32 {
+    let r = set_real_time_hard_limit(audio_buffer_frames, audio_samplerate_hz);
+    if r.is_err() {
+        return 1;
+    }
+    0
+}
+
+}
+}
+
 /// Promote the calling thread thread to real-time priority.
 ///
 /// # Arguments
 ///
 /// * `audio_buffer_frames` - the exact or an upper limit on the number of frames that have to be
 /// rendered each callback, or 0 for a sensible default value.
 /// * `audio_samplerate_hz` - the sample-rate for this audio stream, in Hz.
 ///
@@ -200,9 +463,91 @@ mod tests {
                 Ok(_) => {}
                 Err(e) => {
                     panic!(e);
                 }
             }
             // automatically deallocated, but not demoted until the thread exits.
         }
     }
+    cfg_if! {
+        if #[cfg(target_os = "linux")] {
+            use nix::unistd::*;
+            use nix::sys::signal::*;
+
+            #[test]
+            fn test_linux_api() {
+                {
+                    let info = get_current_thread_info().unwrap();
+                    match promote_thread_to_real_time(info, 512, 44100) {
+                        Ok(_) => {
+                        }
+                        Err(e) => {
+                            panic!(e);
+                        }
+                    }
+                }
+                {
+                    let info = get_current_thread_info().unwrap();
+                    let bytes = info.serialize();
+                    let info2 = RtPriorityThreadInfo::deserialize(bytes);
+                    assert!(info == info2);
+                }
+                {
+                    let info = get_current_thread_info().unwrap();
+                    let bytes = thread_info_serialize(info);
+                    let info2 = thread_info_deserialize(bytes);
+                    assert!(info == info2);
+                }
+            }
+            #[test]
+            fn test_remote_promotion() {
+                let (rd, wr) = pipe().unwrap();
+
+                match fork().expect("fork failed") {
+                    ForkResult::Parent{ child } => {
+                        eprintln!("Parent PID: {}", getpid());
+                        let mut bytes = [0 as u8; std::mem::size_of::<RtPriorityThreadInfo>()];
+                        match read(rd, &mut bytes) {
+                            Ok(_) => {
+                                let info = RtPriorityThreadInfo::deserialize(bytes);
+                                match promote_thread_to_real_time(info, 0, 44100) {
+                                    Ok(_) => {
+                                        eprintln!("thread promotion in the child from the parent succeeded");
+                                        assert!(true);
+                                    }
+                                    Err(_) => {
+                                        eprintln!("promotion Err");
+                                        assert!(false);
+                                    }
+                                }
+                            }
+                            Err(e) => {
+                                eprintln!("could not read from the pipe: {}", e);
+                            }
+                        }
+                        kill(child, SIGKILL).expect("Could not kill the child?");
+                    }
+                    ForkResult::Child => {
+                        let r = set_real_time_hard_limit(0, 44100);
+                        if r.is_err() {
+                            eprintln!("Could not set RT limit, the test will fail.");
+                        }
+                        eprintln!("Child pid: {}", getpid());
+                        let info = get_current_thread_info().unwrap();
+                        let bytes = info.serialize();
+                        match write(wr, &bytes) {
+                            Ok(_) => {
+                                loop {
+                                    std::thread::sleep(std::time::Duration::from_millis(100));
+                                    eprintln!("child sleeping, waiting to be promoted...");
+                                }
+                            }
+                            Err(_) => {
+                                eprintln!("write error on the pipe.");
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
 }
--- a/third_party/rust/audio_thread_priority/src/rt_linux.rs
+++ b/third_party/rust/audio_thread_priority/src/rt_linux.rs
@@ -4,132 +4,239 @@
 
 /* Widely copied from dbus-rs/dbus/examples/rtkit.rs */
 
 extern crate dbus;
 extern crate libc;
 
 use std::cmp;
 use std::error::Error;
+use std::io::Error as OSError;
 
 use dbus::{Connection, BusType, Props, MessageItem, Message};
 
 const DBUS_SOCKET_TIMEOUT: i32 = 10_000;
 const RT_PRIO_DEFAULT: u32 = 10;
 // This is different from libc::pid_t, which is 32 bits, and is defined in sys/types.h.
 #[allow(non_camel_case_types)]
 type kernel_pid_t = libc::c_long;
 
+#[repr(C)]
+#[derive(Clone, Copy)]
+pub struct RtPriorityThreadInfoInternal {
+    /// The PID of the process containing `thread_id` below.
+    pid: libc::pid_t,
+    /// System-wise thread id, use to promote the thread via dbus.
+    thread_id: kernel_pid_t,
+    /// Process-local thread id, used to restore scheduler characteristics. This information is not
+    /// useful in another process, but is useful tied to the `thread_id`, when back into the first
+    /// process.
+    pthread_id: libc::pthread_t,
+    /// ...
+    policy: libc::c_int,
+    /// ...
+    param: libc::sched_param,
+}
+
+impl RtPriorityThreadInfoInternal {
+    /// Serialize a RtPriorityThreadInfoInternal to a byte buffer.
+    pub fn serialize(&self) -> [u8; std::mem::size_of::<Self>()] {
+        unsafe { std::mem::transmute::<Self, [u8; std::mem::size_of::<Self>()]>(*self) }
+    }
+    /// Get an RtPriorityThreadInfoInternal from a byte buffer.
+    pub fn deserialize(bytes: [u8; std::mem::size_of::<Self>()]) -> Self {
+        unsafe { std::mem::transmute::<[u8; std::mem::size_of::<Self>()], Self>(bytes) }
+    }
+}
+
+impl PartialEq for RtPriorityThreadInfoInternal {
+    fn eq(&self, other: &Self) -> bool {
+        self.thread_id == other.thread_id &&
+            self.pthread_id == other.pthread_id
+    }
+}
+
 /*#[derive(Debug)]*/
 pub struct RtPriorityHandleInternal {
-    /// Process-local thread id, used to restore scheduler characteristics.
-    pthread_id: libc::pthread_t,
-    /// The scheduler originaly associated with this thread (probably SCHED_OTHER).
-    policy: libc::c_int,
-    /// The initial priority for this thread.
-    param: libc::sched_param,
+    thread_info: RtPriorityThreadInfoInternal,
 }
 
 fn item_as_i64(i: MessageItem) -> Result<i64, Box<dyn Error>> {
     match i {
         MessageItem::Int32(i) => Ok(i as i64),
         MessageItem::Int64(i) => Ok(i),
         _ => Err(Box::from(&*format!("Property is not integer ({:?})", i)))
     }
 }
 
-fn rtkit_set_realtime(c: &Connection, thread: u64, prio: u32) -> Result<(), Box<dyn Error>> {
-    let mut m = Message::new_method_call("org.freedesktop.RealtimeKit1",
-                                         "/org/freedesktop/RealtimeKit1",
-                                         "org.freedesktop.RealtimeKit1",
-                                         "MakeThreadRealtime")?;
-    m.append_items(&[thread.into(), prio.into()]);
+fn rtkit_set_realtime(thread: u64, pid: u64, prio: u32) -> Result<(), Box<dyn Error>> {
+    let m = if unsafe { libc::getpid() as u64 } == pid {
+        let mut m = Message::new_method_call("org.freedesktop.RealtimeKit1",
+                                             "/org/freedesktop/RealtimeKit1",
+                                             "org.freedesktop.RealtimeKit1",
+                                             "MakeThreadRealtime")?;
+        m.append_items(&[thread.into(), prio.into()]);
+        m
+    } else {
+        let mut m = Message::new_method_call("org.freedesktop.RealtimeKit1",
+                                             "/org/freedesktop/RealtimeKit1",
+                                             "org.freedesktop.RealtimeKit1",
+                                             "MakeThreadRealtimeWithPID")?;
+        m.append_items(&[pid.into(), thread.into(), prio.into()]);
+        m
+    };
+    let c = Connection::get_private(BusType::System)?;
     c.send_with_reply_and_block(m, DBUS_SOCKET_TIMEOUT)?;
     return Ok(());
 }
 
-fn make_realtime(tid: kernel_pid_t, requested_slice_us: u64, prio: u32) -> Result<u32, Box<dyn Error>> {
+/// Returns the maximum priority, maximum real-time time slice, and the current real-time time
+/// slice for this process.
+fn get_limits() -> Result<(i64, u64, libc::rlimit64), Box<dyn Error>> {
     let c = Connection::get_private(BusType::System)?;
 
     let p = Props::new(&c, "org.freedesktop.RealtimeKit1", "/org/freedesktop/RealtimeKit1",
-        "org.freedesktop.RealtimeKit1", DBUS_SOCKET_TIMEOUT);
+                       "org.freedesktop.RealtimeKit1", DBUS_SOCKET_TIMEOUT);
+    let mut current_limit = libc::rlimit64 {
+        rlim_cur: 0,
+        rlim_max: 0
+    };
 
-    // Make sure we don't fail by wanting too much
     let max_prio = item_as_i64(p.get("MaxRealtimePriority")?)?;
     if max_prio < 0 {
         return Err(Box::from("invalid negative MaxRealtimePriority"));
     }
-    let prio = cmp::min(prio, max_prio as u32);
 
-    // Enforce RLIMIT_RTPRIO, also a must before asking rtkit for rtprio
     let max_rttime = item_as_i64(p.get("RTTimeUSecMax")?)?;
     if max_rttime < 0 {
         return Err(Box::from("invalid negative RTTimeUSecMax"));
     }
 
-    // Only take what we need, or cap at the system limit, no further.
-    let rttime_request = cmp::min(requested_slice_us, max_rttime as u64);
-
-    // Set a soft limit to the limit requested, to be able to handle going over the limit using
-    // SIXCPU. Set the hard limit to the maxium slice to prevent getting SIGKILL.
-    let new_limit = libc::rlimit64 { rlim_cur: rttime_request,
-                                     rlim_max: max_rttime as u64 };
-    let mut old_limit = new_limit;
-    if unsafe { libc::getrlimit64(libc::RLIMIT_RTTIME, &mut old_limit) } < 0 {
+    if unsafe { libc::getrlimit64(libc::RLIMIT_RTTIME, &mut current_limit) } < 0 {
+        error!("getrlimit64: {}", OSError::last_os_error().raw_os_error().unwrap());
         return Err(Box::from("getrlimit failed"));
     }
+
+    Ok((max_prio, (max_rttime as u64), current_limit))
+}
+
+fn set_limits(request: u64, max: u64) -> Result<(), Box<dyn Error>> {
+    // Set a soft limit to the limit requested, to be able to handle going over the limit using
+    // SIGXCPU. Set the hard limit to the maxium slice to prevent getting SIGKILL.
+    let new_limit = libc::rlimit64 { rlim_cur: request,
+        rlim_max: max };
     if unsafe { libc::setrlimit64(libc::RLIMIT_RTTIME, &new_limit) } < 0 {
         return Err(Box::from("setrlimit failed"));
     }
 
-    // Finally, let's ask rtkit to make us realtime
-    let r = rtkit_set_realtime(&c, tid as u64, prio);
-
-    if r.is_err() {
-        unsafe { libc::setrlimit64(libc::RLIMIT_RTTIME, &old_limit) };
-        return Err(Box::from("could not set process as real-time."));
-    }
-
-    Ok(prio)
+    Ok(())
 }
 
 pub fn promote_current_thread_to_real_time_internal(audio_buffer_frames: u32,
-                                                    audio_samplerate_hz: u32) -> Result<RtPriorityHandleInternal, ()>
-{
+                                                    audio_samplerate_hz: u32)
+                                           -> Result<RtPriorityHandleInternal, ()> {
+    let thread_info = get_current_thread_info_internal()?;
+    promote_thread_to_real_time_internal(thread_info, audio_buffer_frames, audio_samplerate_hz)
+}
+
+pub fn demote_current_thread_from_real_time_internal(rt_priority_handle: RtPriorityHandleInternal)
+                                            -> Result<(), ()> {
+    assert!(unsafe { libc::pthread_self() } == rt_priority_handle.thread_info.pthread_id);
+
+    if unsafe { libc::pthread_setschedparam(rt_priority_handle.thread_info.pthread_id,
+                                            rt_priority_handle.thread_info.policy,
+                                            &rt_priority_handle.thread_info.param) } < 0 {
+        error!("could not demote thread {}", OSError::last_os_error().raw_os_error().unwrap());
+        return Err(());
+    }
+    return Ok(());
+}
+
+/// This can be called by sandboxed code, it only restores priority to what they were.
+pub fn demote_thread_from_real_time_internal(thread_info: RtPriorityThreadInfoInternal)
+                                            -> Result<(), ()> {
+    let param = unsafe { std::mem::zeroed::<libc::sched_param>() };
+
+    // https://github.com/rust-lang/libc/issues/1511
+    const SCHED_RESET_ON_FORK: libc::c_int = 0x40000000;
+
+    if unsafe { libc::pthread_setschedparam(thread_info.pthread_id,
+                                            libc::SCHED_OTHER|SCHED_RESET_ON_FORK,
+                                            &param) } < 0 {
+        error!("could not demote thread {}", OSError::last_os_error().raw_os_error().unwrap());
+        return Err(());
+    }
+    return Ok(());
+}
+
+/// Get the current thread information, as an opaque struct, that can be serialized and sent
+/// accross processes. This is enough to capture the current state of the scheduling policy, and
+/// an identifier to have another thread promoted to real-time.
+pub fn get_current_thread_info_internal() -> Result<RtPriorityThreadInfoInternal, ()> {
     let thread_id = unsafe { libc::syscall(libc::SYS_gettid) };
     let pthread_id = unsafe { libc::pthread_self() };
     let mut param = unsafe { std::mem::zeroed::<libc::sched_param>() };
     let mut policy = 0;
 
     if unsafe { libc::pthread_getschedparam(pthread_id, &mut policy, &mut param) } < 0 {
-        error!("pthread_getschedparam error {}", pthread_id);
+        error!("pthread_getschedparam error {}", OSError::last_os_error().raw_os_error().unwrap());
         return Err(());
     }
 
+    let pid = unsafe { libc::getpid() };
+
+    Ok(RtPriorityThreadInfoInternal {
+        pid,
+        thread_id,
+        pthread_id,
+        policy,
+        param
+    })
+}
+
+/// This set the RLIMIT_RTTIME resource to something other than "unlimited". It's necessary for the
+/// rtkit request to succeed, and needs to hapen in the child. We can't get the real limit here,
+/// because we don't have access to DBUS, so it is hardcoded to 200ms, which is the default in the
+/// rtkit package.
+pub fn set_real_time_hard_limit_internal(audio_buffer_frames: u32,
+                                         audio_samplerate_hz: u32) -> Result<(), ()> {
     let buffer_frames = if audio_buffer_frames > 0 {
         audio_buffer_frames
     } else {
         // 50ms slice. This "ought to be enough for anybody".
         audio_samplerate_hz / 20
     };
     let budget_us = (buffer_frames * 1_000_000 / audio_samplerate_hz) as u64;
-    let handle = RtPriorityHandleInternal { pthread_id, policy, param};
-    let r = make_realtime(thread_id, budget_us, RT_PRIO_DEFAULT);
-    if r.is_err() {
-        warn!("Could not make thread real-time.");
-        return Err(());
-    }
-    return Ok(handle);
+
+    // It's only necessary to set RLIMIT_RTTIME to something when in the child, skip it if it's a
+    // remoting call.
+    let (_, max_rttime, _) = get_limits().map_err(|_| {})?;
+
+    // Only take what we need, or cap at the system limit, no further.
+    let rttime_request = cmp::min(budget_us, max_rttime as u64);
+    set_limits(rttime_request, max_rttime).map_err(|_| {})?;
+
+    Ok(())
 }
 
-pub fn demote_current_thread_from_real_time_internal(rt_priority_handle: RtPriorityHandleInternal)
-                                            -> Result<(), ()> {
-    assert!(unsafe { libc::pthread_self() } == rt_priority_handle.pthread_id);
+/// Promote a thread (possibly in another process) identified by its tid, to real-time.
+pub fn promote_thread_to_real_time_internal(thread_info: RtPriorityThreadInfoInternal,
+                                            audio_buffer_frames: u32,
+                                            audio_samplerate_hz: u32) -> Result<RtPriorityHandleInternal, ()>
+{
+    let RtPriorityThreadInfoInternal { pid, thread_id, .. } = thread_info;
+
+    let handle = RtPriorityHandleInternal { thread_info };
+
+    let (_, _, limits) = get_limits().map_err(|_| {})?;
+    set_real_time_hard_limit_internal(audio_buffer_frames, audio_samplerate_hz)?;
 
-    if unsafe { libc::pthread_setschedparam(rt_priority_handle.pthread_id,
-                                            rt_priority_handle.policy,
-                                            &rt_priority_handle.param) } < 0 {
-        warn!("could not demote thread {}", rt_priority_handle.pthread_id);
-        return Err(());
+    let r = rtkit_set_realtime(thread_id as u64, pid as u64, RT_PRIO_DEFAULT);
+
+    if r.is_err() {
+        if unsafe { libc::setrlimit64(libc::RLIMIT_RTTIME, &limits) } < 0 {
+            error!("setrlimit64: {}", OSError::last_os_error().raw_os_error().unwrap());
+            return Err(());
+        }
     }
-    return Ok(());
+
+    return Ok(handle);
 }
-
--- a/third_party/rust/bitflags/.cargo-checksum.json
+++ b/third_party/rust/bitflags/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"CHANGELOG.md":"b9f503da2d3c91b0a244f1dc853d975f971f782b209ea52cd4cd98705e6e2749","CODE_OF_CONDUCT.md":"42634d0f6d922f49857175af991802822f7f920487aefa2ee250a50d12251a66","Cargo.toml":"0234b6f827764ca093d897126b45505be0996e67860d61caeab696d092ffb781","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"6b236f8b62c82f189fabce0756e01a2c0ab1f32cb84cad9ff3c96b2ce5282bda","src/example_generated.rs":"e43eb59e90f317f38d436670a6067d2fd9eb35fb319fe716184e4a04e24ed1b2","src/lib.rs":"5751eb6fbb8cb97d8accd0846493168d9b5acff1f8d64435d4da8ad7dbf36b4d"},"package":"228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"77d3d74fbf096e829d46533551f6172026e0607dabfa7245437b5eb684a24305","CODE_OF_CONDUCT.md":"28d69bb291d5f0ba31e2bf1649e1ff08914d4dbf9363a48a61e667fe0136d2ae","Cargo.toml":"2897d56de83b88e8e828cfb944f0c9d8a057fbc0da0f5a4a8c07556fc8c1b6a5","LICENSE-APACHE":"7cfd738c53d61c79f07e348f622bf7707c9084237054d37fbe07788a75f5881c","LICENSE-MIT":"705aaaaecefa087c187bd2eacdb01b8ac1c5ee95b1d5d04d8d7efe0363207df8","README.md":"223ca98599ea77f79293813a67116271676b2a4a7fd6879ef4ea2b7ca90ff587","build.rs":"35a5c69b27bba9b3b5fcf62ab8e37dc47565198d2ae594e34aaf0583e3beeafb","src/example_generated.rs":"4345138fd410405ce5a5c6ba1d256205541aaa7cdfd6f23413dfce432d4efd0c","src/lib.rs":"dad0185ea71001b8ab33f967fed4a249b853999af84ca597872f520139471c34"},"package":"8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2"}
\ No newline at end of file
--- a/third_party/rust/bitflags/CHANGELOG.md
+++ b/third_party/rust/bitflags/CHANGELOG.md
@@ -1,108 +1,143 @@
-# 1.0.3
-
-- Improve zero value flag handling and documentation ([#157])
-
-[#157]: https://github.com/rust-lang-nursery/bitflags/pull/157
-
-# 1.0.2
-
-- 30% improvement in compile time of bitflags crate ([#156])
-
-- Documentation improvements ([#153])
-
-- Implementation cleanup ([#149])
-
-[#156]: https://github.com/rust-lang-nursery/bitflags/pull/156
-[#153]: https://github.com/rust-lang-nursery/bitflags/pull/153
-[#149]: https://github.com/rust-lang-nursery/bitflags/pull/149
-
-# 1.0.1
-- Add support for `pub(restricted)` specifier on the bitflags struct ([#135])
-- Optimize performance of `all()` when called from a separate crate ([#136])
-
-[#135]: https://github.com/rust-lang-nursery/bitflags/pull/135
-[#136]: https://github.com/rust-lang-nursery/bitflags/pull/136
-
-# 1.0.0
-- **[breaking change]** Macro now generates [associated constants](https://doc.rust-lang.org/reference/items.html#associated-constants) ([#24])
-
-- **[breaking change]** Minimum supported version is Rust **1.20**, due to usage of associated constants
-
-- After being broken in 0.9, the `#[deprecated]` attribute is now supported again ([#112])
-
-- Other improvements to unit tests and documentation ([#106] and [#115])
-
-[#24]: https://github.com/rust-lang-nursery/bitflags/pull/24
-[#106]: https://github.com/rust-lang-nursery/bitflags/pull/106
-[#112]: https://github.com/rust-lang-nursery/bitflags/pull/112
-[#115]: https://github.com/rust-lang-nursery/bitflags/pull/115
-
-## How to update your code to use associated constants
-Assuming the following structure definition:
-```rust
-bitflags! {
-  struct Something: u8 {
-     const FOO = 0b01,
-     const BAR = 0b10
-  }
-}
-```
-In 0.9 and older you could do:
-```rust
-let x = FOO.bits | BAR.bits;
-```
-Now you must use:
-```rust
-let x = Something::FOO.bits | Something::BAR.bits;
-```
-
-# 0.9.1
-- Fix the implementation of `Formatting` traits when other formatting traits were present in scope ([#105])
-
-[#105]: https://github.com/rust-lang-nursery/bitflags/pull/105
-
-# 0.9.0
-- **[breaking change]** Use struct keyword instead of flags to define bitflag types ([#84])
-
-- **[breaking change]** Terminate const items with semicolons instead of commas ([#87])
-
-- Implement the `Hex`, `Octal`, and `Binary` formatting traits ([#86])
-
-- Printing an empty flag value with the `Debug` trait now prints "(empty)" instead of nothing ([#85])
-
-- The `bitflags!` macro can now be used inside of a fn body, to define a type local to that function ([#74])
-
-[#74]: https://github.com/rust-lang-nursery/bitflags/pull/74
-[#84]: https://github.com/rust-lang-nursery/bitflags/pull/84
-[#85]: https://github.com/rust-lang-nursery/bitflags/pull/85
-[#86]: https://github.com/rust-lang-nursery/bitflags/pull/86
-[#87]: https://github.com/rust-lang-nursery/bitflags/pull/87
-
-# 0.8.2
-- Update feature flag used when building bitflags as a dependency of the Rust toolchain
-
-# 0.8.1
-- Allow bitflags to be used as a dependency of the Rust toolchain
-
-# 0.8.0
-- Add support for the experimental `i128` and `u128` integer types ([#57])
-- Add set method: `flags.set(SOME_FLAG, true)` or `flags.set(SOME_FLAG, false)` ([#55])
-  This may break code that defines its own set method
-
-[#55]: https://github.com/rust-lang-nursery/bitflags/pull/55
-[#57]: https://github.com/rust-lang-nursery/bitflags/pull/57
-
-# 0.7.1
-*(yanked)*
-
-# 0.7.0
-- Implement the Extend trait ([#49])
-- Allow definitions inside the `bitflags!` macro to refer to items imported from other modules ([#51])
-
-[#49]: https://github.com/rust-lang-nursery/bitflags/pull/49
-[#51]: https://github.com/rust-lang-nursery/bitflags/pull/51
-
-# 0.6.0
-- The `no_std` feature was removed as it is now the default
-- The `assignment_operators` feature was remove as it is now enabled by default
-- Some clippy suggestions have been applied
+# 1.2.0
+
+- Fix typo: {Lower, Upper}Exp - {Lower, Upper}Hex ([#183])
+
+- Add support for "unknown" bits ([#188])
+
+[#183]: https://github.com/rust-lang-nursery/bitflags/pull/183
+[#188]: https://github.com/rust-lang-nursery/bitflags/pull/188
+
+# 1.1.0
+
+This is a re-release of `1.0.5`, which was yanked due to a bug in the RLS.
+
+# 1.0.5
+
+- Use compiletest_rs flags supported by stable toolchain ([#171])
+
+- Put the user provided attributes first ([#173])
+
+- Make bitflags methods `const` on newer compilers ([#175])
+
+[#171]: https://github.com/rust-lang-nursery/bitflags/pull/171
+[#173]: https://github.com/rust-lang-nursery/bitflags/pull/173
+[#175]: https://github.com/rust-lang-nursery/bitflags/pull/175
+
+# 1.0.4
+
+- Support Rust 2018 style macro imports ([#165])
+
+  ```rust
+  use bitflags::bitflags;
+  ```
+
+[#165]: https://github.com/rust-lang-nursery/bitflags/pull/165
+
+# 1.0.3
+
+- Improve zero value flag handling and documentation ([#157])
+
+[#157]: https://github.com/rust-lang-nursery/bitflags/pull/157
+
+# 1.0.2
+
+- 30% improvement in compile time of bitflags crate ([#156])
+
+- Documentation improvements ([#153])
+
+- Implementation cleanup ([#149])
+
+[#156]: https://github.com/rust-lang-nursery/bitflags/pull/156
+[#153]: https://github.com/rust-lang-nursery/bitflags/pull/153
+[#149]: https://github.com/rust-lang-nursery/bitflags/pull/149
+
+# 1.0.1
+- Add support for `pub(restricted)` specifier on the bitflags struct ([#135])
+- Optimize performance of `all()` when called from a separate crate ([#136])
+
+[#135]: https://github.com/rust-lang-nursery/bitflags/pull/135
+[#136]: https://github.com/rust-lang-nursery/bitflags/pull/136
+
+# 1.0.0
+- **[breaking change]** Macro now generates [associated constants](https://doc.rust-lang.org/reference/items.html#associated-constants) ([#24])
+
+- **[breaking change]** Minimum supported version is Rust **1.20**, due to usage of associated constants
+
+- After being broken in 0.9, the `#[deprecated]` attribute is now supported again ([#112])
+
+- Other improvements to unit tests and documentation ([#106] and [#115])
+
+[#24]: https://github.com/rust-lang-nursery/bitflags/pull/24
+[#106]: https://github.com/rust-lang-nursery/bitflags/pull/106
+[#112]: https://github.com/rust-lang-nursery/bitflags/pull/112
+[#115]: https://github.com/rust-lang-nursery/bitflags/pull/115
+
+## How to update your code to use associated constants
+Assuming the following structure definition:
+```rust
+bitflags! {
+  struct Something: u8 {
+     const FOO = 0b01,
+     const BAR = 0b10
+  }
+}
+```
+In 0.9 and older you could do:
+```rust
+let x = FOO.bits | BAR.bits;
+```
+Now you must use:
+```rust
+let x = Something::FOO.bits | Something::BAR.bits;
+```
+
+# 0.9.1
+- Fix the implementation of `Formatting` traits when other formatting traits were present in scope ([#105])
+
+[#105]: https://github.com/rust-lang-nursery/bitflags/pull/105
+
+# 0.9.0
+- **[breaking change]** Use struct keyword instead of flags to define bitflag types ([#84])
+
+- **[breaking change]** Terminate const items with semicolons instead of commas ([#87])
+
+- Implement the `Hex`, `Octal`, and `Binary` formatting traits ([#86])
+
+- Printing an empty flag value with the `Debug` trait now prints "(empty)" instead of nothing ([#85])
+
+- The `bitflags!` macro can now be used inside of a fn body, to define a type local to that function ([#74])
+
+[#74]: https://github.com/rust-lang-nursery/bitflags/pull/74
+[#84]: https://github.com/rust-lang-nursery/bitflags/pull/84
+[#85]: https://github.com/rust-lang-nursery/bitflags/pull/85
+[#86]: https://github.com/rust-lang-nursery/bitflags/pull/86
+[#87]: https://github.com/rust-lang-nursery/bitflags/pull/87
+
+# 0.8.2
+- Update feature flag used when building bitflags as a dependency of the Rust toolchain
+
+# 0.8.1
+- Allow bitflags to be used as a dependency of the Rust toolchain
+
+# 0.8.0
+- Add support for the experimental `i128` and `u128` integer types ([#57])
+- Add set method: `flags.set(SOME_FLAG, true)` or `flags.set(SOME_FLAG, false)` ([#55])
+  This may break code that defines its own set method
+
+[#55]: https://github.com/rust-lang-nursery/bitflags/pull/55
+[#57]: https://github.com/rust-lang-nursery/bitflags/pull/57
+
+# 0.7.1
+*(yanked)*
+
+# 0.7.0
+- Implement the Extend trait ([#49])
+- Allow definitions inside the `bitflags!` macro to refer to items imported from other modules ([#51])
+
+[#49]: https://github.com/rust-lang-nursery/bitflags/pull/49
+[#51]: https://github.com/rust-lang-nursery/bitflags/pull/51
+
+# 0.6.0
+- The `no_std` feature was removed as it is now the default
+- The `assignment_operators` feature was remove as it is now enabled by default
+- Some clippy suggestions have been applied
--- a/third_party/rust/bitflags/CODE_OF_CONDUCT.md
+++ b/third_party/rust/bitflags/CODE_OF_CONDUCT.md
@@ -1,73 +1,73 @@
-# Contributor Covenant Code of Conduct
-
-## Our Pledge
-
-In the interest of fostering an open and welcoming environment, we as
-contributors and maintainers pledge to making participation in our project and
-our community a harassment-free experience for everyone, regardless of age, body
-size, disability, ethnicity, gender identity and expression, level of experience,
-education, socio-economic status, nationality, personal appearance, race,
-religion, or sexual identity and orientation.
-
-## Our Standards
-
-Examples of behavior that contributes to creating a positive environment
-include:
-
-* Using welcoming and inclusive language
-* Being respectful of differing viewpoints and experiences
-* Gracefully accepting constructive criticism
-* Focusing on what is best for the community
-* Showing empathy towards other community members
-
-Examples of unacceptable behavior by participants include:
-
-* The use of sexualized language or imagery and unwelcome sexual attention or
-  advances
-* Trolling, insulting/derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or electronic
-  address, without explicit permission
-* Other conduct which could reasonably be considered inappropriate in a
-  professional setting
-
-## Our Responsibilities
-
-Project maintainers are responsible for clarifying the standards of acceptable
-behavior and are expected to take appropriate and fair corrective action in
-response to any instances of unacceptable behavior.
-
-Project maintainers have the right and responsibility to remove, edit, or
-reject comments, commits, code, wiki edits, issues, and other contributions
-that are not aligned to this Code of Conduct, or to ban temporarily or
-permanently any contributor for other behaviors that they deem inappropriate,
-threatening, offensive, or harmful.
-
-## Scope
-
-This Code of Conduct applies both within project spaces and in public spaces
-when an individual is representing the project or its community. Examples of
-representing a project or community include using an official project e-mail
-address, posting via an official social media account, or acting as an appointed
-representative at an online or offline event. Representation of a project may be
-further defined and clarified by project maintainers.
-
-## Enforcement
-
-Instances of abusive, harassing, or otherwise unacceptable behavior may be
-reported by contacting the project team at coc@senaite.org. All
-complaints will be reviewed and investigated and will result in a response that
-is deemed necessary and appropriate to the circumstances. The project team is
-obligated to maintain confidentiality with regard to the reporter of an incident.
-Further details of specific enforcement policies may be posted separately.
-
-Project maintainers who do not follow or enforce the Code of Conduct in good
-faith may face temporary or permanent repercussions as determined by other
-members of the project's leadership.
-
-## Attribution
-
-This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
-available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
-
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+education, socio-economic status, nationality, personal appearance, race,
+religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+  advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+  address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+  professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at coc@senaite.org. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
 [homepage]: https://www.contributor-covenant.org
\ No newline at end of file
--- a/third_party/rust/bitflags/Cargo.toml
+++ b/third_party/rust/bitflags/Cargo.toml
@@ -1,24 +1,25 @@
 # 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
+# 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 = "bitflags"
-version = "1.0.4"
+version = "1.2.0"
 authors = ["The Rust Project Developers"]
+build = "build.rs"
 exclude = [".travis.yml", "appveyor.yml", "bors.toml"]
 description = "A macro to generate structures which behave like bitflags.\n"
 homepage = "https://github.com/bitflags/bitflags"
 documentation = "https://docs.rs/bitflags"
 readme = "README.md"
 keywords = ["bit", "bitmask", "bitflags", "flags"]
 categories = ["no-std"]
 license = "MIT/Apache-2.0"
--- a/third_party/rust/bitflags/LICENSE-APACHE
+++ b/third_party/rust/bitflags/LICENSE-APACHE
@@ -1,201 +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.
+                              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.
--- a/third_party/rust/bitflags/LICENSE-MIT
+++ b/third_party/rust/bitflags/LICENSE-MIT
@@ -1,25 +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.
+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.
--- a/third_party/rust/bitflags/README.md
+++ b/third_party/rust/bitflags/README.md
@@ -1,34 +1,34 @@
-bitflags
-========
-
-[![Build Status](https://travis-ci.com/bitflags/bitflags.svg?branch=master)](https://travis-ci.com/bitflags/bitflags)
-[![Join the chat at https://gitter.im/bitflags/Lobby](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bitflags/Lobby?utm_source=badge&utm_medium=badge&utm_content=badge)
-[![Latest version](https://img.shields.io/crates/v/bitflags.svg)](https://crates.io/crates/bitflags)
-[![Documentation](https://docs.rs/bitflags/badge.svg)](https://docs.rs/bitflags)
-![Minimum rustc version](https://img.shields.io/badge/rustc-1.20+-yellow.svg)
-![License](https://img.shields.io/crates/l/bitflags.svg)
-
-A Rust macro to generate structures which behave like a set of bitflags
-
-- [Documentation](https://docs.rs/bitflags)
-- [Release notes](https://github.com/bitflags/bitflags/releases)
-
-## Usage
-
-Add this to your `Cargo.toml`:
-
-```toml
-[dependencies]
-bitflags = "1.0"
-```
-
-and this to your crate root:
-
-```rust
-#[macro_use]
-extern crate bitflags;
-```
-
-## Rust Version Support
-
-The minimum supported Rust version is 1.20 due to use of associated constants.
+bitflags
+========
+
+[![Build Status](https://travis-ci.com/bitflags/bitflags.svg?branch=master)](https://travis-ci.com/bitflags/bitflags)
+[![Join the chat at https://gitter.im/bitflags/Lobby](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bitflags/Lobby?utm_source=badge&utm_medium=badge&utm_content=badge)
+[![Latest version](https://img.shields.io/crates/v/bitflags.svg)](https://crates.io/crates/bitflags)
+[![Documentation](https://docs.rs/bitflags/badge.svg)](https://docs.rs/bitflags)
+![Minimum rustc version](https://img.shields.io/badge/rustc-1.20+-yellow.svg)
+![License](https://img.shields.io/crates/l/bitflags.svg)
+
+A Rust macro to generate structures which behave like a set of bitflags
+
+- [Documentation](https://docs.rs/bitflags)
+- [Release notes](https://github.com/bitflags/bitflags/releases)
+
+## Usage
+
+Add this to your `Cargo.toml`:
+
+```toml
+[dependencies]
+bitflags = "1.0"
+```
+
+and this to your crate root:
+
+```rust
+#[macro_use]
+extern crate bitflags;
+```
+
+## Rust Version Support
+
+The minimum supported Rust version is 1.20 due to use of associated constants.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/bitflags/build.rs
@@ -0,0 +1,44 @@
+use std::env;
+use std::process::Command;
+use std::str::{self, FromStr};
+
+fn main(){
+    let minor = match rustc_minor_version() {
+        Some(minor) => minor,
+        None => return,
+    };
+
+    // const fn stabilized in Rust 1.31:
+    if minor >= 31 {
+        println!("cargo:rustc-cfg=bitflags_const_fn");
+    }
+}
+
+fn rustc_minor_version() -> Option<u32> {
+    let rustc = match env::var_os("RUSTC") {
+        Some(rustc) => rustc,
+        None => return None,
+    };
+
+    let output = match Command::new(rustc).arg("--version").output() {
+        Ok(output) => output,
+        Err(_) => return None,
+    };
+
+    let version = match str::from_utf8(&output.stdout) {
+        Ok(version) => version,
+        Err(_) => return None,
+    };
+
+    let mut pieces = version.split('.');
+    if pieces.next() != Some("rustc 1") {
+        return None;
+    }
+
+    let next = match pieces.next() {
+        Some(next) => next,
+        None => return None,
+    };
+
+    u32::from_str(next).ok()
+}
\ No newline at end of file
--- a/third_party/rust/bitflags/src/example_generated.rs
+++ b/third_party/rust/bitflags/src/example_generated.rs
@@ -1,14 +1,14 @@
-//! This module shows an example of code generated by the macro. **IT MUST NOT BE USED OUTSIDE THIS
-//! CRATE**.
-
-bitflags! {
-    /// This is the same `Flags` struct defined in the [crate level example](../index.html#example).
-    /// Note that this struct is just for documentation purposes only, it must not be used outside
-    /// this crate.
-    pub struct Flags: u32 {
-        const A = 0b00000001;
-        const B = 0b00000010;
-        const C = 0b00000100;
-        const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
-    }
-}
+//! This module shows an example of code generated by the macro. **IT MUST NOT BE USED OUTSIDE THIS
+//! CRATE**.
+
+bitflags! {
+    /// This is the same `Flags` struct defined in the [crate level example](../index.html#example).
+    /// Note that this struct is just for documentation purposes only, it must not be used outside
+    /// this crate.
+    pub struct Flags: u32 {
+        const A = 0b00000001;
+        const B = 0b00000010;
+        const C = 0b00000100;
+        const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
+    }
+}
--- a/third_party/rust/bitflags/src/lib.rs
+++ b/third_party/rust/bitflags/src/lib.rs
@@ -1,1229 +1,1432 @@
-// Copyright 2014 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 typesafe bitmask flag generator useful for sets of C-style bitmask flags.
-//! It can be used for creating typesafe wrappers around C APIs.
-//!
-//! The `bitflags!` macro generates a `struct` that manages a set of flags. The
-//! flags should only be defined for integer types, otherwise unexpected type
-//! errors may occur at compile time.
-//!
-//! # Example
-//!
-//! ```
-//! #[macro_use]
-//! extern crate bitflags;
-//!
-//! bitflags! {
-//!     struct Flags: u32 {
-//!         const A = 0b00000001;
-//!         const B = 0b00000010;
-//!         const C = 0b00000100;
-//!         const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
-//!     }
-//! }
-//!
-//! fn main() {
-//!     let e1 = Flags::A | Flags::C;
-//!     let e2 = Flags::B | Flags::C;
-//!     assert_eq!((e1 | e2), Flags::ABC);   // union
-//!     assert_eq!((e1 & e2), Flags::C);     // intersection
-//!     assert_eq!((e1 - e2), Flags::A);     // set difference
-//!     assert_eq!(!e2, Flags::A);           // set complement
-//! }
-//! ```
-//!
-//! See [`example_generated::Flags`](./example_generated/struct.Flags.html) for documentation of code
-//! generated by the above `bitflags!` expansion.
-//!
-//! The generated `struct`s can also be extended with type and trait
-//! implementations:
-//!
-//! ```
-//! #[macro_use]
-//! extern crate bitflags;
-//!
-//! use std::fmt;
-//!
-//! bitflags! {
-//!     struct Flags: u32 {
-//!         const A = 0b00000001;
-//!         const B = 0b00000010;
-//!     }
-//! }
-//!
-//! impl Flags {
-//!     pub fn clear(&mut self) {
-//!         self.bits = 0;  // The `bits` field can be accessed from within the
-//!                         // same module where the `bitflags!` macro was invoked.
-//!     }
-//! }
-//!
-//! impl fmt::Display for Flags {
-//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-//!         write!(f, "hi!")
-//!     }
-//! }
-//!
-//! fn main() {
-//!     let mut flags = Flags::A | Flags::B;
-//!     flags.clear();
-//!     assert!(flags.is_empty());
-//!     assert_eq!(format!("{}", flags), "hi!");
-//!     assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B");
-//!     assert_eq!(format!("{:?}", Flags::B), "B");
-//! }
-//! ```
-//!
-//! # Visibility
-//!
-//! The generated struct and its associated flag constants are not exported
-//! out of the current module by default. A definition can be exported out of
-//! the current module by adding `pub` before `flags`:
-//!
-//! ```
-//! #[macro_use]
-//! extern crate bitflags;
-//!
-//! mod example {
-//!     bitflags! {
-//!         pub struct Flags1: u32 {
-//!             const A = 0b00000001;
-//!         }
-//!     }
-//!     bitflags! {
-//! #       pub
-//!         struct Flags2: u32 {
-//!             const B = 0b00000010;
-//!         }
-//!     }
-//! }
-//!
-//! fn main() {
-//!     let flag1 = example::Flags1::A;
-//!     let flag2 = example::Flags2::B; // error: const `B` is private
-//! }
-//! ```
-//!
-//! # Attributes
-//!
-//! Attributes can be attached to the generated `struct` by placing them
-//! before the `flags` keyword.
-//!
-//! # Trait implementations
-//!
-//! The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash`
-//! traits automatically derived for the `struct` using the `derive` attribute.
-//! Additional traits can be derived by providing an explicit `derive`
-//! attribute on `flags`.
-//!
-//! The `Extend` and `FromIterator` traits are implemented for the `struct`,
-//! too: `Extend` adds the union of the instances of the `struct` iterated over,
-//! while `FromIterator` calculates the union.
-//!
-//! The `Binary`, `Debug`, `LowerExp`, `Octal` and `UpperExp` trait is also
-//! implemented by displaying the bits value of the internal struct.
-//!
-//! ## Operators
-//!
-//! The following operator traits are implemented for the generated `struct`:
-//!
-//! - `BitOr` and `BitOrAssign`: union
-//! - `BitAnd` and `BitAndAssign`: intersection
-//! - `BitXor` and `BitXorAssign`: toggle
-//! - `Sub` and `SubAssign`: set difference
-//! - `Not`: set complement
-//!
-//! # Methods
-//!
-//! The following methods are defined for the generated `struct`:
-//!
-//! - `empty`: an empty set of flags
-//! - `all`: the set of all flags
-//! - `bits`: the raw value of the flags currently stored
-//! - `from_bits`: convert from underlying bit representation, unless that
-//!                representation contains bits that do not correspond to a flag
-//! - `from_bits_truncate`: convert from underlying bit representation, dropping
-//!                         any bits that do not correspond to flags
-//! - `is_empty`: `true` if no flags are currently stored
-//! - `is_all`: `true` if all flags are currently set
-//! - `intersects`: `true` if there are flags common to both `self` and `other`
-//! - `contains`: `true` all of the flags in `other` are contained within `self`
-//! - `insert`: inserts the specified flags in-place
-//! - `remove`: removes the specified flags in-place
-//! - `toggle`: the specified flags will be inserted if not present, and removed
-//!             if they are.
-//! - `set`: inserts or removes the specified flags depending on the passed value
-//!
-//! ## Default
-//!
-//! The `Default` trait is not automatically implemented for the generated struct.
-//!
-//! If your default value is equal to `0` (which is the same value as calling `empty()`
-//! on the generated struct), you can simply derive `Default`:
-//!
-//! ```
-//! #[macro_use]
-//! extern crate bitflags;
-//!
-//! bitflags! {
-//!     // Results in default value with bits: 0
-//!     #[derive(Default)]
-//!     struct Flags: u32 {
-//!         const A = 0b00000001;
-//!         const B = 0b00000010;
-//!         const C = 0b00000100;
-//!     }
-//! }
-//!
-//! fn main() {
-//!     let derived_default: Flags = Default::default();
-//!     assert_eq!(derived_default.bits(), 0);
-//! }
-//! ```
-//!
-//! If your default value is not equal to `0` you need to implement `Default` yourself:
-//!
-//! ```
-//! #[macro_use]
-//! extern crate bitflags;
-//!
-//! bitflags! {
-//!     struct Flags: u32 {
-//!         const A = 0b00000001;
-//!         const B = 0b00000010;
-//!         const C = 0b00000100;
-//!     }
-//! }
-//!
-//! // explicit `Default` implementation
-//! impl Default for Flags {
-//!     fn default() -> Flags {
-//!         Flags::A | Flags::C
-//!     }
-//! }
-//!
-//! fn main() {
-//!     let implemented_default: Flags = Default::default();
-//!     assert_eq!(implemented_default, (Flags::A | Flags::C));
-//! }
-//! ```
-//!
-//! # Zero Flags
-//!
-//! Flags with a value equal to zero will have some strange behavior that one should be aware of.
-//!
-//! ```
-//! #[macro_use]
-//! extern crate bitflags;
-//!
-//! bitflags! {
-//!     struct Flags: u32 {
-//!         const NONE = 0b00000000;
-//!         const SOME = 0b00000001;
-//!     }
-//! }
-//!
-//! fn main() {
-//!     let empty = Flags::empty();
-//!     let none = Flags::NONE;
-//!     let some = Flags::SOME;
-//!
-//!     // Zero flags are treated as always present
-//!     assert!(empty.contains(Flags::NONE));
-//!     assert!(none.contains(Flags::NONE));
-//!     assert!(some.contains(Flags::NONE));
-//!
-//!     // Zero flags will be ignored when testing for emptiness
-//!     assert!(none.is_empty());
-//! }
-//! ```
-
-#![no_std]
-#![doc(html_root_url = "https://docs.rs/bitflags/1.0.4")]
-
-#[cfg(test)]
-#[macro_use]
-extern crate std;
-
-// Re-export libcore using an alias so that the macros can work without
-// requiring `extern crate core` downstream.
-#[doc(hidden)]
-pub extern crate core as _core;
-
-/// The macro used to generate the flag structure.
-///
-/// See the [crate level docs](../bitflags/index.html) for complete documentation.
-///
-/// # Example
-///
-/// ```
-/// #[macro_use]
-/// extern crate bitflags;
-///
-/// bitflags! {
-///     struct Flags: u32 {
-///         const A = 0b00000001;
-///         const B = 0b00000010;
-///         const C = 0b00000100;
-///         const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
-///     }
-/// }
-///
-/// fn main() {
-///     let e1 = Flags::A | Flags::C;
-///     let e2 = Flags::B | Flags::C;
-///     assert_eq!((e1 | e2), Flags::ABC);   // union
-///     assert_eq!((e1 & e2), Flags::C);     // intersection
-///     assert_eq!((e1 - e2), Flags::A);     // set difference
-///     assert_eq!(!e2, Flags::A);           // set complement
-/// }
-/// ```
-///
-/// The generated `struct`s can also be extended with type and trait
-/// implementations:
-///
-/// ```
-/// #[macro_use]
-/// extern crate bitflags;
-///
-/// use std::fmt;
-///
-/// bitflags! {
-///     struct Flags: u32 {
-///         const A = 0b00000001;
-///         const B = 0b00000010;
-///     }
-/// }
-///
-/// impl Flags {
-///     pub fn clear(&mut self) {
-///         self.bits = 0;  // The `bits` field can be accessed from within the
-///                         // same module where the `bitflags!` macro was invoked.
-///     }
-/// }
-///
-/// impl fmt::Display for Flags {
-///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-///         write!(f, "hi!")
-///     }
-/// }
-///
-/// fn main() {
-///     let mut flags = Flags::A | Flags::B;
-///     flags.clear();
-///     assert!(flags.is_empty());
-///     assert_eq!(format!("{}", flags), "hi!");
-///     assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B");
-///     assert_eq!(format!("{:?}", Flags::B), "B");
-/// }
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! bitflags {
-    (
-        $(#[$outer:meta])*
-        pub struct $BitFlags:ident: $T:ty {
-            $(
-                $(#[$inner:ident $($args:tt)*])*
-                const $Flag:ident = $value:expr;
-            )+
-        }
-    ) => {
-        __bitflags! {
-            $(#[$outer])*
-            (pub) $BitFlags: $T {
-                $(
-                    $(#[$inner $($args)*])*
-                    $Flag = $value;
-                )+
-            }
-        }
-    };
-    (
-        $(#[$outer:meta])*
-        struct $BitFlags:ident: $T:ty {
-            $(
-                $(#[$inner:ident $($args:tt)*])*
-                const $Flag:ident = $value:expr;
-            )+
-        }
-    ) => {
-        __bitflags! {
-            $(#[$outer])*
-            () $BitFlags: $T {
-                $(
-                    $(#[$inner $($args)*])*
-                    $Flag = $value;
-                )+
-            }
-        }
-    };
-    (
-        $(#[$outer:meta])*
-        pub ($($vis:tt)+) struct $BitFlags:ident: $T:ty {
-            $(
-                $(#[$inner:ident $($args:tt)*])*
-                const $Flag:ident = $value:expr;
-            )+
-        }
-    ) => {
-        __bitflags! {
-            $(#[$outer])*
-            (pub ($($vis)+)) $BitFlags: $T {
-                $(
-                    $(#[$inner $($args)*])*
-                    $Flag = $value;
-                )+
-            }
-        }
-    };
-}
-
-#[macro_export(local_inner_macros)]
-#[doc(hidden)]
-macro_rules! __bitflags {
-    (
-        $(#[$outer:meta])*
-        ($($vis:tt)*) $BitFlags:ident: $T:ty {
-            $(
-                $(#[$inner:ident $($args:tt)*])*
-                $Flag:ident = $value:expr;
-            )+
-        }
-    ) => {
-        #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
-        $(#[$outer])*
-        $($vis)* struct $BitFlags {
-            bits: $T,
-        }
-
-        __impl_bitflags! {
-            $BitFlags: $T {
-                $(
-                    $(#[$inner $($args)*])*
-                    $Flag = $value;
-                )+
-            }
-        }
-    };
-}
-
-#[macro_export(local_inner_macros)]
-#[doc(hidden)]
-macro_rules! __impl_bitflags {
-    (
-        $BitFlags:ident: $T:ty {
-            $(
-                $(#[$attr:ident $($args:tt)*])*
-                $Flag:ident = $value:expr;
-            )+
-        }
-    ) => {
-        impl $crate::_core::fmt::Debug for $BitFlags {
-            fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result {
-                // This convoluted approach is to handle #[cfg]-based flag
-                // omission correctly. For example it needs to support:
-                //
-                //    #[cfg(unix)] const A: Flag = /* ... */;
-                //    #[cfg(windows)] const B: Flag = /* ... */;
-
-                // Unconditionally define a check for every flag, even disabled
-                // ones.
-                #[allow(non_snake_case)]
-                trait __BitFlags {
-                    $(
-                        #[inline]
-                        fn $Flag(&self) -> bool { false }
-                    )+
-                }
-
-                // Conditionally override the check for just those flags that
-                // are not #[cfg]ed away.
-                impl __BitFlags for $BitFlags {
-                    $(
-                        __impl_bitflags! {
-                            #[allow(deprecated)]
-                            #[inline]
-                            $(? #[$attr $($args)*])*
-                            fn $Flag(&self) -> bool {
-                                if Self::$Flag.bits == 0 && self.bits != 0 {
-                                    false
-                                } else {
-                                    self.bits & Self::$Flag.bits == Self::$Flag.bits
-                                }
-                            }
-                        }
-                    )+
-                }
-
-                let mut first = true;
-                $(
-                    if <$BitFlags as __BitFlags>::$Flag(self) {
-                        if !first {
-                            f.write_str(" | ")?;
-                        }
-                        first = false;
-                        f.write_str(__bitflags_stringify!($Flag))?;
-                    }
-                )+
-                if first {
-                    f.write_str("(empty)")?;
-                }
-                Ok(())
-            }
-        }
-        impl $crate::_core::fmt::Binary for $BitFlags {
-            fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result {
-                $crate::_core::fmt::Binary::fmt(&self.bits, f)
-            }
-        }
-        impl $crate::_core::fmt::Octal for $BitFlags {
-            fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result {
-                $crate::_core::fmt::Octal::fmt(&self.bits, f)
-            }
-        }
-        impl $crate::_core::fmt::LowerHex for $BitFlags {
-            fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result {
-                $crate::_core::fmt::LowerHex::fmt(&self.bits, f)
-            }
-        }
-        impl $crate::_core::fmt::UpperHex for $BitFlags {
-            fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result {
-                $crate::_core::fmt::UpperHex::fmt(&self.bits, f)
-            }
-        }
-
-        #[allow(dead_code)]
-        impl $BitFlags {
-            $(
-                $(#[$attr $($args)*])*
-                pub const $Flag: $BitFlags = $BitFlags { bits: $value };
-            )+
-
-            /// Returns an empty set of flags.
-            #[inline]
-            pub fn empty() -> $BitFlags {
-                $BitFlags { bits: 0 }
-            }
-
-            /// Returns the set containing all flags.
-            #[inline]
-            pub fn all() -> $BitFlags {
-                // See `Debug::fmt` for why this approach is taken.
-                #[allow(non_snake_case)]
-                trait __BitFlags {
-                    $(
-                        #[inline]
-                        fn $Flag() -> $T { 0 }
-                    )+
-                }
-                impl __BitFlags for $BitFlags {
-                    $(
-                        __impl_bitflags! {
-                            #[allow(deprecated)]
-                            #[inline]
-                            $(? #[$attr $($args)*])*
-                            fn $Flag() -> $T { Self::$Flag.bits }
-                        }
-                    )+
-                }
-                $BitFlags { bits: $(<$BitFlags as __BitFlags>::$Flag())|+ }
-            }
-
-            /// Returns the raw value of the flags currently stored.
-            #[inline]
-            pub fn bits(&self) -> $T {
-                self.bits
-            }
-
-            /// Convert from underlying bit representation, unless that
-            /// representation contains bits that do not correspond to a flag.
-            #[inline]
-            pub fn from_bits(bits: $T) -> $crate::_core::option::Option<$BitFlags> {
-                if (bits & !$BitFlags::all().bits()) == 0 {
-                    $crate::_core::option::Option::Some($BitFlags { bits })
-                } else {
-                    $crate::_core::option::Option::None
-                }
-            }
-
-            /// Convert from underlying bit representation, dropping any bits
-            /// that do not correspond to flags.
-            #[inline]
-            pub fn from_bits_truncate(bits: $T) -> $BitFlags {
-                $BitFlags { bits } & $BitFlags::all()
-            }
-
-            /// Returns `true` if no flags are currently stored.
-            #[inline]
-            pub fn is_empty(&self) -> bool {
-                *self == $BitFlags::empty()
-            }
-
-            /// Returns `true` if all flags are currently set.
-            #[inline]
-            pub fn is_all(&self) -> bool {
-                *self == $BitFlags::all()
-            }
-
-            /// Returns `true` if there are flags common to both `self` and `other`.
-            #[inline]
-            pub fn intersects(&self, other: $BitFlags) -> bool {
-                !(*self & other).is_empty()
-            }
-
-            /// Returns `true` all of the flags in `other` are contained within `self`.
-            #[inline]
-            pub fn contains(&self, other: $BitFlags) -> bool {
-                (*self & other) == other
-            }
-
-            /// Inserts the specified flags in-place.
-            #[inline]
-            pub fn insert(&mut self, other: $BitFlags) {
-                self.bits |= other.bits;
-            }
-
-            /// Removes the specified flags in-place.
-            #[inline]
-            pub fn remove(&mut self, other: $BitFlags) {
-                self.bits &= !other.bits;
-            }
-
-            /// Toggles the specified flags in-place.
-            #[inline]
-            pub fn toggle(&mut self, other: $BitFlags) {
-                self.bits ^= other.bits;
-            }
-
-            /// Inserts or removes the specified flags depending on the passed value.
-            #[inline]
-            pub fn set(&mut self, other: $BitFlags, value: bool) {
-                if value {
-                    self.insert(other);
-                } else {
-                    self.remove(other);
-                }
-            }
-        }
-
-        impl $crate::_core::ops::BitOr for $BitFlags {
-            type Output = $BitFlags;
-
-            /// Returns the union of the two sets of flags.
-            #[inline]
-            fn bitor(self, other: $BitFlags) -> $BitFlags {
-                $BitFlags { bits: self.bits | other.bits }
-            }
-        }
-
-        impl $crate::_core::ops::BitOrAssign for $BitFlags {
-
-            /// Adds the set of flags.
-            #[inline]
-            fn bitor_assign(&mut self, other: $BitFlags) {
-                self.bits |= other.bits;
-            }
-        }
-
-        impl $crate::_core::ops::BitXor for $BitFlags {
-            type Output = $BitFlags;
-
-            /// Returns the left flags, but with all the right flags toggled.
-            #[inline]
-            fn bitxor(self, other: $BitFlags) -> $BitFlags {
-                $BitFlags { bits: self.bits ^ other.bits }
-            }
-        }
-
-        impl $crate::_core::ops::BitXorAssign for $BitFlags {
-
-            /// Toggles the set of flags.
-            #[inline]
-            fn bitxor_assign(&mut self, other: $BitFlags) {
-                self.bits ^= other.bits;
-            }
-        }
-
-        impl $crate::_core::ops::BitAnd for $BitFlags {
-            type Output = $BitFlags;
-
-            /// Returns the intersection between the two sets of flags.
-            #[inline]
-            fn bitand(self, other: $BitFlags) -> $BitFlags {
-                $BitFlags { bits: self.bits & other.bits }
-            }
-        }
-
-        impl $crate::_core::ops::BitAndAssign for $BitFlags {
-
-            /// Disables all flags disabled in the set.
-            #[inline]
-            fn bitand_assign(&mut self, other: $BitFlags) {
-                self.bits &= other.bits;
-            }
-        }
-
-        impl $crate::_core::ops::Sub for $BitFlags {
-            type Output = $BitFlags;
-
-            /// Returns the set difference of the two sets of flags.
-            #[inline]
-            fn sub(self, other: $BitFlags) -> $BitFlags {
-                $BitFlags { bits: self.bits & !other.bits }
-            }
-        }
-
-        impl $crate::_core::ops::SubAssign for $BitFlags {
-
-            /// Disables all flags enabled in the set.
-            #[inline]
-            fn sub_assign(&mut self, other: $BitFlags) {
-                self.bits &= !other.bits;
-            }
-        }
-
-        impl $crate::_core::ops::Not for $BitFlags {
-            type Output = $BitFlags;
-
-            /// Returns the complement of this set of flags.
-            #[inline]
-            fn not(self) -> $BitFlags {
-                $BitFlags { bits: !self.bits } & $BitFlags::all()
-            }
-        }
-
-        impl $crate::_core::iter::Extend<$BitFlags> for $BitFlags {
-            fn extend<T: $crate::_core::iter::IntoIterator<Item=$BitFlags>>(&mut self, iterator: T) {
-                for item in iterator {
-                    self.insert(item)
-                }
-            }
-        }
-
-        impl $crate::_core::iter::FromIterator<$BitFlags> for $BitFlags {
-            fn from_iter<T: $crate::_core::iter::IntoIterator<Item=$BitFlags>>(iterator: T) -> $BitFlags {
-                let mut result = Self::empty();
-                result.extend(iterator);
-                result
-            }
-        }
-    };
-
-    // Every attribute that the user writes on a const is applied to the
-    // corresponding const that we generate, but within the implementation of
-    // Debug and all() we want to ignore everything but #[cfg] attributes. In
-    // particular, including a #[deprecated] attribute on those items would fail
-    // to compile.
-    // https://github.com/bitflags/bitflags/issues/109
-    //
-    // Input:
-    //
-    //     ? #[cfg(feature = "advanced")]
-    //     ? #[deprecated(note = "Use somthing else.")]
-    //     ? #[doc = r"High quality documentation."]
-    //     fn f() -> i32 { /* ... */ }
-    //
-    // Output:
-    //
-    //     #[cfg(feature = "advanced")]
-    //     fn f() -> i32 { /* ... */ }
-    (
-        $(#[$filtered:meta])*
-        ? #[cfg $($cfgargs:tt)*]
-        $(? #[$rest:ident $($restargs:tt)*])*
-        fn $($item:tt)*
-    ) => {
-        __impl_bitflags! {
-            $(#[$filtered])*
-            #[cfg $($cfgargs)*]
-            $(? #[$rest $($restargs)*])*
-            fn $($item)*
-        }
-    };
-    (
-        $(#[$filtered:meta])*
-        // $next != `cfg`
-        ? #[$next:ident $($nextargs:tt)*]
-        $(? #[$rest:ident $($restargs:tt)*])*
-        fn $($item:tt)*
-    ) => {
-        __impl_bitflags! {
-            $(#[$filtered])*
-            // $next filtered out
-            $(? #[$rest $($restargs)*])*
-            fn $($item)*
-        }
-    };
-    (
-        $(#[$filtered:meta])*
-        fn $($item:tt)*
-    ) => {
-        $(#[$filtered])*
-        fn $($item)*
-    };
-}
-
-// Same as std::stringify but callable from __impl_bitflags, which needs to use
-// local_inner_macros so can only directly call macros from this crate.
-#[macro_export]
-#[doc(hidden)]
-macro_rules! __bitflags_stringify {
-    ($s:ident) => {
-        stringify!($s)
-    };
-}
-
-#[cfg(feature = "example_generated")]
-pub mod example_generated;
-
-#[cfg(test)]
-mod tests {
-    use std::collections::hash_map::DefaultHasher;
-    use std::hash::{Hash, Hasher};
-
-    bitflags! {
-        #[doc = "> The first principle is that you must not fool yourself — and"]
-        #[doc = "> you are the easiest person to fool."]
-        #[doc = "> "]
-        #[doc = "> - Richard Feynman"]
-        struct Flags: u32 {
-            const A = 0b00000001;
-            #[doc = "<pcwalton> macros are way better at generating code than trans is"]
-            const B = 0b00000010;
-            const C = 0b00000100;
-            #[doc = "* cmr bed"]
-            #[doc = "* strcat table"]
-            #[doc = "<strcat> wait what?"]
-            const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
-        }
-    }
-
-    bitflags! {
-        struct _CfgFlags: u32 {
-            #[cfg(windows)]
-            const _CFG_A = 0b01;
-            #[cfg(unix)]
-            const _CFG_B = 0b01;
-            #[cfg(windows)]
-            const _CFG_C = _CFG_A.bits | 0b10;
-        }
-    }
-
-    bitflags! {
-        struct AnotherSetOfFlags: i8 {
-            const ANOTHER_FLAG = -1_i8;
-        }
-    }
-
-    bitflags! {
-        struct LongFlags: u32 {
-            const LONG_A = 0b1111111111111111;
-        }
-    }
-
-    #[test]
-    fn test_bits() {
-        assert_eq!(Flags::empty().bits(), 0b00000000);
-        assert_eq!(Flags::A.bits(), 0b00000001);
-        assert_eq!(Flags::ABC.bits(), 0b00000111);
-
-        assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00);
-        assert_eq!(AnotherSetOfFlags::ANOTHER_FLAG.bits(), !0_i8);
-    }
-
-    #[test]
-    fn test_from_bits() {
-        assert_eq!(Flags::from_bits(0), Some(Flags::empty()));
-        assert_eq!(Flags::from_bits(0b1), Some(Flags::A));
-        assert_eq!(Flags::from_bits(0b10), Some(Flags::B));
-        assert_eq!(Flags::from_bits(0b11), Some(Flags::A | Flags::B));
-        assert_eq!(Flags::from_bits(0b1000), None);
-
-        assert_eq!(
-            AnotherSetOfFlags::from_bits(!0_i8),
-            Some(AnotherSetOfFlags::ANOTHER_FLAG)
-        );
-    }
-
-    #[test]
-    fn test_from_bits_truncate() {
-        assert_eq!(Flags::from_bits_truncate(0), Flags::empty());
-        assert_eq!(Flags::from_bits_truncate(0b1), Flags::A);
-        assert_eq!(Flags::from_bits_truncate(0b10), Flags::B);
-        assert_eq!(Flags::from_bits_truncate(0b11), (Flags::A | Flags::B));
-        assert_eq!(Flags::from_bits_truncate(0b1000), Flags::empty());
-        assert_eq!(Flags::from_bits_truncate(0b1001), Flags::A);
-
-        assert_eq!(
-            AnotherSetOfFlags::from_bits_truncate(0_i8),
-            AnotherSetOfFlags::empty()
-        );
-    }
-
-    #[test]
-    fn test_is_empty() {
-        assert!(Flags::empty().is_empty());
-        assert!(!Flags::A.is_empty());
-        assert!(!Flags::ABC.is_empty());
-
-        assert!(!AnotherSetOfFlags::ANOTHER_FLAG.is_empty());
-    }
-
-    #[test]
-    fn test_is_all() {
-        assert!(Flags::all().is_all());
-        assert!(!Flags::A.is_all());
-        assert!(Flags::ABC.is_all());
-
-        assert!(AnotherSetOfFlags::ANOTHER_FLAG.is_all());
-    }
-
-    #[test]
-    fn test_two_empties_do_not_intersect() {
-        let e1 = Flags::empty();
-        let e2 = Flags::empty();
-        assert!(!e1.intersects(e2));
-
-        assert!(AnotherSetOfFlags::ANOTHER_FLAG.intersects(AnotherSetOfFlags::ANOTHER_FLAG));
-    }
-
-    #[test]
-    fn test_empty_does_not_intersect_with_full() {
-        let e1 = Flags::empty();
-        let e2 = Flags::ABC;
-        assert!(!e1.intersects(e2));
-    }
-
-    #[test]
-    fn test_disjoint_intersects() {
-        let e1 = Flags::A;
-        let e2 = Flags::B;
-        assert!(!e1.intersects(e2));
-    }
-
-    #[test]
-    fn test_overlapping_intersects() {
-        let e1 = Flags::A;
-        let e2 = Flags::A | Flags::B;
-        assert!(e1.intersects(e2));
-    }
-
-    #[test]
-    fn test_contains() {
-        let e1 = Flags::A;
-        let e2 = Flags::A | Flags::B;
-        assert!(!e1.contains(e2));
-        assert!(e2.contains(e1));
-        assert!(Flags::ABC.contains(e2));
-
-        assert!(AnotherSetOfFlags::ANOTHER_FLAG.contains(AnotherSetOfFlags::ANOTHER_FLAG));
-    }
-
-    #[test]
-    fn test_insert() {
-        let mut e1 = Flags::A;
-        let e2 = Flags::A | Flags::B;
-        e1.insert(e2);
-        assert_eq!(e1, e2);
-
-        let mut e3 = AnotherSetOfFlags::empty();
-        e3.insert(AnotherSetOfFlags::ANOTHER_FLAG);
-        assert_eq!(e3, AnotherSetOfFlags::ANOTHER_FLAG);
-    }
-
-    #[test]
-    fn test_remove() {
-        let mut e1 = Flags::A | Flags::B;
-        let e2 = Flags::A | Flags::C;
-        e1.remove(e2);
-        assert_eq!(e1, Flags::B);
-
-        let mut e3 = AnotherSetOfFlags::ANOTHER_FLAG;
-        e3.remove(AnotherSetOfFlags::ANOTHER_FLAG);
-        assert_eq!(e3, AnotherSetOfFlags::empty());
-    }
-
-    #[test]
-    fn test_operators() {
-        let e1 = Flags::A | Flags::C;
-        let e2 = Flags::B | Flags::C;
-        assert_eq!((e1 | e2), Flags::ABC); // union
-        assert_eq!((e1 & e2), Flags::C); // intersection
-        assert_eq!((e1 - e2), Flags::A); // set difference
-        assert_eq!(!e2, Flags::A); // set complement
-        assert_eq!(e1 ^ e2, Flags::A | Flags::B); // toggle
-        let mut e3 = e1;
-        e3.toggle(e2);
-        assert_eq!(e3, Flags::A | Flags::B);
-
-        let mut m4 = AnotherSetOfFlags::empty();
-        m4.toggle(AnotherSetOfFlags::empty());
-        assert_eq!(m4, AnotherSetOfFlags::empty());
-    }
-
-    #[test]
-    fn test_set() {
-        let mut e1 = Flags::A | Flags::C;
-        e1.set(Flags::B, true);
-        e1.set(Flags::C, false);
-
-        assert_eq!(e1, Flags::A | Flags::B);
-    }
-
-    #[test]
-    fn test_assignment_operators() {
-        let mut m1 = Flags::empty();
-        let e1 = Flags::A | Flags::C;
-        // union
-        m1 |= Flags::A;
-        assert_eq!(m1, Flags::A);
-        // intersection
-        m1 &= e1;
-        assert_eq!(m1, Flags::A);
-        // set difference
-        m1 -= m1;
-        assert_eq!(m1, Flags::empty());
-        // toggle
-        m1 ^= e1;
-        assert_eq!(m1, e1);
-    }
-
-    #[test]
-    fn test_extend() {
-        let mut flags;
-
-        flags = Flags::empty();
-        flags.extend([].iter().cloned());
-        assert_eq!(flags, Flags::empty());
-
-        flags = Flags::empty();
-        flags.extend([Flags::A, Flags::B].iter().cloned());
-        assert_eq!(flags, Flags::A | Flags::B);
-
-        flags = Flags::A;
-        flags.extend([Flags::A, Flags::B].iter().cloned());
-        assert_eq!(flags, Flags::A | Flags::B);
-
-        flags = Flags::B;
-        flags.extend([Flags::A, Flags::ABC].iter().cloned());
-        assert_eq!(flags, Flags::ABC);
-    }
-
-    #[test]
-    fn test_from_iterator() {
-        assert_eq!([].iter().cloned().collect::<Flags>(), Flags::empty());
-        assert_eq!(
-            [Flags::A, Flags::B].iter().cloned().collect::<Flags>(),
-            Flags::A | Flags::B
-        );
-        assert_eq!(
-            [Flags::A, Flags::ABC].iter().cloned().collect::<Flags>(),
-            Flags::ABC
-        );
-    }
-
-    #[test]
-    fn test_lt() {
-        let mut a = Flags::empty();
-        let mut b = Flags::empty();
-
-        assert!(!(a < b) && !(b < a));
-        b = Flags::B;
-        assert!(a < b);
-        a = Flags::C;
-        assert!(!(a < b) && b < a);
-        b = Flags::C | Flags::B;
-        assert!(a < b);
-    }
-
-    #[test]
-    fn test_ord() {
-        let mut a = Flags::empty();
-        let mut b = Flags::empty();
-
-        assert!(a <= b && a >= b);
-        a = Flags::A;
-        assert!(a > b && a >= b);
-        assert!(b < a && b <= a);
-        b = Flags::B;
-        assert!(b > a && b >= a);
-        assert!(a < b && a <= b);
-    }
-
-    fn hash<T: Hash>(t: &T) -> u64 {
-        let mut s = DefaultHasher::new();
-        t.hash(&mut s);
-        s.finish()
-    }
-
-    #[test]
-    fn test_hash() {
-        let mut x = Flags::empty();
-        let mut y = Flags::empty();
-        assert_eq!(hash(&x), hash(&y));
-        x = Flags::all();
-        y = Flags::ABC;
-        assert_eq!(hash(&x), hash(&y));
-    }
-
-    #[test]
-    fn test_debug() {
-        assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B");
-        assert_eq!(format!("{:?}", Flags::empty()), "(empty)");
-        assert_eq!(format!("{:?}", Flags::ABC), "A | B | C | ABC");
-    }
-
-    #[test]
-    fn test_binary() {
-        assert_eq!(format!("{:b}", Flags::ABC), "111");
-        assert_eq!(format!("{:#b}", Flags::ABC), "0b111");
-    }
-
-    #[test]
-    fn test_octal() {
-        assert_eq!(format!("{:o}", LongFlags::LONG_A), "177777");
-        assert_eq!(format!("{:#o}", LongFlags::LONG_A), "0o177777");
-    }
-
-    #[test]
-    fn test_lowerhex() {
-        assert_eq!(format!("{:x}", LongFlags::LONG_A), "ffff");
-        assert_eq!(format!("{:#x}", LongFlags::LONG_A), "0xffff");
-    }
-
-    #[test]
-    fn test_upperhex() {
-        assert_eq!(format!("{:X}", LongFlags::LONG_A), "FFFF");
-        assert_eq!(format!("{:#X}", LongFlags::LONG_A), "0xFFFF");
-    }
-
-    mod submodule {
-        bitflags! {
-            pub struct PublicFlags: i8 {
-                const X = 0;
-            }
-        }
-        bitflags! {
-            struct PrivateFlags: i8 {
-                const Y = 0;
-            }
-        }
-
-        #[test]
-        fn test_private() {
-            let _ = PrivateFlags::Y;
-        }
-    }
-
-    #[test]
-    fn test_public() {
-        let _ = submodule::PublicFlags::X;
-    }
-
-    mod t1 {
-        mod foo {
-            pub type Bar = i32;
-        }
-
-        bitflags! {
-            /// baz
-            struct Flags: foo::Bar {
-                const A = 0b00000001;
-                #[cfg(foo)]
-                const B = 0b00000010;
-                #[cfg(foo)]
-                const C = 0b00000010;
-            }
-        }
-    }
-
-    #[test]
-    fn test_in_function() {
-        bitflags! {
-           struct Flags: u8 {
-                const A = 1;
-                #[cfg(any())] // false
-                const B = 2;
-            }
-        }
-        assert_eq!(Flags::all(), Flags::A);
-        assert_eq!(format!("{:?}", Flags::A), "A");
-    }
-
-    #[test]
-    fn test_deprecated() {
-        bitflags! {
-            pub struct TestFlags: u32 {
-                #[deprecated(note = "Use something else.")]
-                const ONE = 1;
-            }
-        }
-    }
-
-    #[test]
-    fn test_pub_crate() {
-        mod module {
-            bitflags! {
-                pub (crate) struct Test: u8 {
-                    const FOO = 1;
-                }
-            }
-        }
-
-        assert_eq!(module::Test::FOO.bits(), 1);
-    }
-
-    #[test]
-    fn test_pub_in_module() {
-        mod module {
-            mod submodule {
-                bitflags! {
-                    // `pub (in super)` means only the module `module` will
-                    // be able to access this.
-                    pub (in super) struct Test: u8 {
-                        const FOO = 1;
-                    }
-                }
-            }
-
-            mod test {
-                // Note: due to `pub (in super)`,
-                // this cannot be accessed directly by the testing code.
-                pub(super) fn value() -> u8 {
-                    super::submodule::Test::FOO.bits()
-                }
-            }
-
-            pub fn value() -> u8 {
-                test::value()
-            }
-        }
-
-        assert_eq!(module::value(), 1)
-    }
-
-    #[test]
-    fn test_zero_value_flags() {
-        bitflags! {
-            struct Flags: u32 {
-                const NONE = 0b0;
-                const SOME = 0b1;
-            }
-        }
-
-        assert!(Flags::empty().contains(Flags::NONE));
-        assert!(Flags::SOME.contains(Flags::NONE));
-        assert!(Flags::NONE.is_empty());
-
-        assert_eq!(format!("{:?}", Flags::empty()), "NONE");
-        assert_eq!(format!("{:?}", Flags::SOME), "SOME");
-    }
-}
+// Copyright 2014 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 typesafe bitmask flag generator useful for sets of C-style bitmask flags.
+//! It can be used for creating typesafe wrappers around C APIs.
+//!
+//! The `bitflags!` macro generates a `struct` that manages a set of flags. The
+//! flags should only be defined for integer types, otherwise unexpected type
+//! errors may occur at compile time.
+//!
+//! # Example
+//!
+//! ```
+//! #[macro_use]
+//! extern crate bitflags;
+//!
+//! bitflags! {
+//!     struct Flags: u32 {
+//!         const A = 0b00000001;
+//!         const B = 0b00000010;
+//!         const C = 0b00000100;
+//!         const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
+//!     }
+//! }
+//!
+//! fn main() {
+//!     let e1 = Flags::A | Flags::C;
+//!     let e2 = Flags::B | Flags::C;
+//!     assert_eq!((e1 | e2), Flags::ABC);   // union
+//!     assert_eq!((e1 & e2), Flags::C);     // intersection
+//!     assert_eq!((e1 - e2), Flags::A);     // set difference
+//!     assert_eq!(!e2, Flags::A);           // set complement
+//! }
+//! ```
+//!
+//! See [`example_generated::Flags`](./example_generated/struct.Flags.html) for documentation of code
+//! generated by the above `bitflags!` expansion.
+//!
+//! The generated `struct`s can also be extended with type and trait
+//! implementations:
+//!
+//! ```
+//! #[macro_use]
+//! extern crate bitflags;
+//!
+//! use std::fmt;
+//!
+//! bitflags! {
+//!     struct Flags: u32 {
+//!         const A = 0b00000001;
+//!         const B = 0b00000010;
+//!     }
+//! }
+//!
+//! impl Flags {
+//!     pub fn clear(&mut self) {
+//!         self.bits = 0;  // The `bits` field can be accessed from within the
+//!                         // same module where the `bitflags!` macro was invoked.
+//!     }
+//! }
+//!
+//! impl fmt::Display for Flags {
+//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+//!         write!(f, "hi!")
+//!     }
+//! }
+//!
+//! fn main() {
+//!     let mut flags = Flags::A | Flags::B;
+//!     flags.clear();
+//!     assert!(flags.is_empty());
+//!     assert_eq!(format!("{}", flags), "hi!");
+//!     assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B");
+//!     assert_eq!(format!("{:?}", Flags::B), "B");
+//! }
+//! ```
+//!
+//! # Visibility
+//!
+//! The generated struct and its associated flag constants are not exported
+//! out of the current module by default. A definition can be exported out of
+//! the current module by adding `pub` before `flags`:
+//!
+//! ```
+//! #[macro_use]
+//! extern crate bitflags;
+//!
+//! mod example {
+//!     bitflags! {
+//!         pub struct Flags1: u32 {
+//!             const A = 0b00000001;
+//!         }
+//!     }
+//!     bitflags! {
+//! #       pub
+//!         struct Flags2: u32 {
+//!             const B = 0b00000010;
+//!         }
+//!     }
+//! }
+//!
+//! fn main() {
+//!     let flag1 = example::Flags1::A;
+//!     let flag2 = example::Flags2::B; // error: const `B` is private
+//! }
+//! ```
+//!
+//! # Attributes
+//!
+//! Attributes can be attached to the generated `struct` by placing them
+//! before the `flags` keyword.
+//!
+//! # Trait implementations
+//!
+//! The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash`
+//! traits automatically derived for the `struct` using the `derive` attribute.
+//! Additional traits can be derived by providing an explicit `derive`
+//! attribute on `flags`.
+//!
+//! The `Extend` and `FromIterator` traits are implemented for the `struct`,
+//! too: `Extend` adds the union of the instances of the `struct` iterated over,
+//! while `FromIterator` calculates the union.
+//!
+//! The `Binary`, `Debug`, `LowerHex`, `Octal` and `UpperHex` trait is also
+//! implemented by displaying the bits value of the internal struct.
+//!
+//! ## Operators
+//!
+//! The following operator traits are implemented for the generated `struct`:
+//!
+//! - `BitOr` and `BitOrAssign`: union
+//! - `BitAnd` and `BitAndAssign`: intersection
+//! - `BitXor` and `BitXorAssign`: toggle
+//! - `Sub` and `SubAssign`: set difference
+//! - `Not`: set complement
+//!
+//! # Methods
+//!
+//! The following methods are defined for the generated `struct`:
+//!
+//! - `empty`: an empty set of flags
+//! - `all`: the set of all defined flags
+//! - `bits`: the raw value of the flags currently stored
+//! - `from_bits`: convert from underlying bit representation, unless that
+//!                representation contains bits that do not correspond to a
+//!                defined flag
+//! - `from_bits_truncate`: convert from underlying bit representation, dropping
+//!                         any bits that do not correspond to defined flags
+//! - `from_bits_unchecked`: convert from underlying bit representation, keeping
+//!                          all bits (even those not corresponding to defined
+//!                          flags)
+//! - `is_empty`: `true` if no flags are currently stored
+//! - `is_all`: `true` if currently set flags exactly equal all defined flags
+//! - `intersects`: `true` if there are flags common to both `self` and `other`
+//! - `contains`: `true` all of the flags in `other` are contained within `self`
+//! - `insert`: inserts the specified flags in-place
+//! - `remove`: removes the specified flags in-place
+//! - `toggle`: the specified flags will be inserted if not present, and removed
+//!             if they are.
+//! - `set`: inserts or removes the specified flags depending on the passed value
+//!
+//! ## Default
+//!
+//! The `Default` trait is not automatically implemented for the generated struct.
+//!
+//! If your default value is equal to `0` (which is the same value as calling `empty()`
+//! on the generated struct), you can simply derive `Default`:
+//!
+//! ```
+//! #[macro_use]
+//! extern crate bitflags;
+//!
+//! bitflags! {
+//!     // Results in default value with bits: 0
+//!     #[derive(Default)]
+//!     struct Flags: u32 {
+//!         const A = 0b00000001;
+//!         const B = 0b00000010;
+//!         const C = 0b00000100;
+//!     }
+//! }
+//!
+//! fn main() {
+//!     let derived_default: Flags = Default::default();
+//!     assert_eq!(derived_default.bits(), 0);
+//! }
+//! ```
+//!
+//! If your default value is not equal to `0` you need to implement `Default` yourself:
+//!
+//! ```
+//! #[macro_use]
+//! extern crate bitflags;
+//!
+//! bitflags! {
+//!     struct Flags: u32 {
+//!         const A = 0b00000001;
+//!         const B = 0b00000010;
+//!         const C = 0b00000100;
+//!     }
+//! }
+//!
+//! // explicit `Default` implementation
+//! impl Default for Flags {
+//!     fn default() -> Flags {
+//!         Flags::A | Flags::C
+//!     }
+//! }
+//!
+//! fn main() {
+//!     let implemented_default: Flags = Default::default();
+//!     assert_eq!(implemented_default, (Flags::A | Flags::C));
+//! }
+//! ```
+//!
+//! # Zero Flags
+//!
+//! Flags with a value equal to zero will have some strange behavior that one should be aware of.
+//!
+//! ```
+//! #[macro_use]
+//! extern crate bitflags;
+//!
+//! bitflags! {
+//!     struct Flags: u32 {
+//!         const NONE = 0b00000000;
+//!         const SOME = 0b00000001;
+//!     }
+//! }
+//!
+//! fn main() {
+//!     let empty = Flags::empty();
+//!     let none = Flags::NONE;
+//!     let some = Flags::SOME;
+//!
+//!     // Zero flags are treated as always present
+//!     assert!(empty.contains(Flags::NONE));
+//!     assert!(none.contains(Flags::NONE));
+//!     assert!(some.contains(Flags::NONE));
+//!
+//!     // Zero flags will be ignored when testing for emptiness
+//!     assert!(none.is_empty());
+//! }
+//! ```
+
+#![no_std]
+#![doc(html_root_url = "https://docs.rs/bitflags/1.2.0")]
+
+#[cfg(test)]
+#[macro_use]
+extern crate std;
+
+// Re-export libcore using an alias so that the macros can work without
+// requiring `extern crate core` downstream.
+#[doc(hidden)]
+pub extern crate core as _core;
+
+/// The macro used to generate the flag structure.
+///
+/// See the [crate level docs](../bitflags/index.html) for complete documentation.
+///
+/// # Example
+///
+/// ```
+/// #[macro_use]
+/// extern crate bitflags;
+///
+/// bitflags! {
+///     struct Flags: u32 {
+///         const A = 0b00000001;
+///         const B = 0b00000010;
+///         const C = 0b00000100;
+///         const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
+///     }
+/// }
+///
+/// fn main() {
+///     let e1 = Flags::A | Flags::C;
+///     let e2 = Flags::B | Flags::C;
+///     assert_eq!((e1 | e2), Flags::ABC);   // union
+///     assert_eq!((e1 & e2), Flags::C);     // intersection
+///     assert_eq!((e1 - e2), Flags::A);     // set difference
+///     assert_eq!(!e2, Flags::A);           // set complement
+/// }
+/// ```
+///
+/// The generated `struct`s can also be extended with type and trait
+/// implementations:
+///
+/// ```
+/// #[macro_use]
+/// extern crate bitflags;
+///
+/// use std::fmt;
+///
+/// bitflags! {
+///     struct Flags: u32 {
+///         const A = 0b00000001;
+///         const B = 0b00000010;
+///     }
+/// }
+///
+/// impl Flags {
+///     pub fn clear(&mut self) {
+///         self.bits = 0;  // The `bits` field can be accessed from within the
+///                         // same module where the `bitflags!` macro was invoked.
+///     }
+/// }
+///
+/// impl fmt::Display for Flags {
+///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+///         write!(f, "hi!")
+///     }
+/// }
+///
+/// fn main() {
+///     let mut flags = Flags::A | Flags::B;
+///     flags.clear();
+///     assert!(flags.is_empty());
+///     assert_eq!(format!("{}", flags), "hi!");
+///     assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B");
+///     assert_eq!(format!("{:?}", Flags::B), "B");
+/// }
+/// ```
+#[macro_export(local_inner_macros)]
+macro_rules! bitflags {
+    (
+        $(#[$outer:meta])*
+        pub struct $BitFlags:ident: $T:ty {
+            $(
+                $(#[$inner:ident $($args:tt)*])*
+                const $Flag:ident = $value:expr;
+            )+
+        }
+    ) => {
+        __bitflags! {
+            $(#[$outer])*
+            (pub) $BitFlags: $T {
+                $(
+                    $(#[$inner $($args)*])*
+                    $Flag = $value;
+                )+
+            }
+        }
+    };
+    (
+        $(#[$outer:meta])*
+        struct $BitFlags:ident: $T:ty {
+            $(
+                $(#[$inner:ident $($args:tt)*])*
+                const $Flag:ident = $value:expr;
+            )+
+        }
+    ) => {
+        __bitflags! {
+            $(#[$outer])*
+            () $BitFlags: $T {
+                $(
+                    $(#[$inner $($args)*])*
+                    $Flag = $value;
+                )+
+            }
+        }
+    };
+    (
+        $(#[$outer:meta])*
+        pub ($($vis:tt)+) struct $BitFlags:ident: $T:ty {
+            $(
+                $(#[$inner:ident $($args:tt)*])*
+                const $Flag:ident = $value:expr;
+            )+
+        }
+    ) => {
+        __bitflags! {
+            $(#[$outer])*
+            (pub ($($vis)+)) $BitFlags: $T {
+                $(
+                    $(#[$inner $($args)*])*
+                    $Flag = $value;
+                )+
+            }
+        }
+    };
+}
+
+#[macro_export(local_inner_macros)]
+#[doc(hidden)]
+macro_rules! __bitflags {
+    (
+        $(#[$outer:meta])*
+        ($($vis:tt)*) $BitFlags:ident: $T:ty {
+            $(
+                $(#[$inner:ident $($args:tt)*])*
+                $Flag:ident = $value:expr;
+            )+
+        }
+    ) => {
+        $(#[$outer])*
+        #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
+        $($vis)* struct $BitFlags {
+            bits: $T,
+        }
+
+        __impl_bitflags! {
+            $BitFlags: $T {
+                $(
+                    $(#[$inner $($args)*])*
+                    $Flag = $value;
+                )+
+            }
+        }
+    };
+}
+
+#[macro_export(local_inner_macros)]
+#[doc(hidden)]
+#[cfg(bitflags_const_fn)]
+macro_rules! __fn_bitflags {
+    (
+        $(# $attr_args:tt)*
+        const fn $($item:tt)*
+    ) => {
+        $(# $attr_args)*
+        const fn $($item)*
+    };
+    (
+        $(# $attr_args:tt)*
+        pub const fn $($item:tt)*
+    ) => {
+        $(# $attr_args)*
+        pub const fn $($item)*
+    };
+    (
+        $(# $attr_args:tt)*
+        pub const unsafe fn $($item:tt)*
+    ) => {
+        $(# $attr_args)*
+        pub const unsafe fn $($item)*
+    };
+}
+
+#[macro_export(local_inner_macros)]
+#[doc(hidden)]
+#[cfg(not(bitflags_const_fn))]
+macro_rules! __fn_bitflags {
+    (
+        $(# $attr_args:tt)*
+        const fn $($item:tt)*
+    ) => {
+        $(# $attr_args)*
+        fn $($item)*
+    };
+    (
+        $(# $attr_args:tt)*
+        pub const fn $($item:tt)*
+    ) => {
+        $(# $attr_args)*
+        pub fn $($item)*
+    };
+    (
+        $(# $attr_args:tt)*
+        pub const unsafe fn $($item:tt)*
+    ) => {
+        $(# $attr_args)*
+        pub unsafe fn $($item)*
+    };
+}
+
+#[macro_export(local_inner_macros)]
+#[doc(hidden)]
+macro_rules! __impl_bitflags {
+    (
+        $BitFlags:ident: $T:ty {
+            $(
+                $(#[$attr:ident $($args:tt)*])*
+                $Flag:ident = $value:expr;
+            )+
+        }
+    ) => {
+        impl $crate::_core::fmt::Debug for $BitFlags {
+            fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result {
+                // This convoluted approach is to handle #[cfg]-based flag
+                // omission correctly. For example it needs to support:
+                //
+                //    #[cfg(unix)] const A: Flag = /* ... */;
+                //    #[cfg(windows)] const B: Flag = /* ... */;
+
+                // Unconditionally define a check for every flag, even disabled
+                // ones.
+                #[allow(non_snake_case)]
+                trait __BitFlags {
+                    $(
+                        #[inline]
+                        fn $Flag(&self) -> bool { false }
+                    )+
+                }
+
+                // Conditionally override the check for just those flags that
+                // are not #[cfg]ed away.
+                impl __BitFlags for $BitFlags {
+                    $(
+                        __impl_bitflags! {
+                            #[allow(deprecated)]
+                            #[inline]
+                            $(? #[$attr $($args)*])*
+                            fn $Flag(&self) -> bool {
+                                if Self::$Flag.bits == 0 && self.bits != 0 {
+                                    false
+                                } else {
+                                    self.bits & Self::$Flag.bits == Self::$Flag.bits
+                                }
+                            }
+                        }
+                    )+
+                }
+
+                let mut first = true;
+                $(
+                    if <$BitFlags as __BitFlags>::$Flag(self) {
+                        if !first {
+                            f.write_str(" | ")?;
+                        }
+                        first = false;
+                        f.write_str(__bitflags_stringify!($Flag))?;
+                    }
+                )+
+                let extra_bits = self.bits & !$BitFlags::all().bits();
+                if extra_bits != 0 {
+                    if !first {
+                        f.write_str(" | ")?;
+                    }
+                    first = false;
+                    f.write_str("0x")?;
+                    $crate::_core::fmt::LowerHex::fmt(&extra_bits, f)?;
+                }
+                if first {
+                    f.write_str("(empty)")?;
+                }
+                Ok(())
+            }
+        }
+        impl $crate::_core::fmt::Binary for $BitFlags {
+            fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result {
+                $crate::_core::fmt::Binary::fmt(&self.bits, f)
+            }
+        }
+        impl $crate::_core::fmt::Octal for $BitFlags {
+            fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result {
+                $crate::_core::fmt::Octal::fmt(&self.bits, f)
+            }
+        }
+        impl $crate::_core::fmt::LowerHex for $BitFlags {
+            fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result {
+                $crate::_core::fmt::LowerHex::fmt(&self.bits, f)
+            }
+        }
+        impl $crate::_core::fmt::UpperHex for $BitFlags {
+            fn fmt(&self, f: &mut $crate::_core::fmt::Formatter) -> $crate::_core::fmt::Result {
+                $crate::_core::fmt::UpperHex::fmt(&self.bits, f)
+            }
+        }
+
+        #[allow(dead_code)]
+        impl $BitFlags {
+            $(
+                $(#[$attr $($args)*])*
+                pub const $Flag: $BitFlags = $BitFlags { bits: $value };
+            )+
+
+            __fn_bitflags! {
+                /// Returns an empty set of flags
+                #[inline]
+                pub const fn empty() -> $BitFlags {
+                    $BitFlags { bits: 0 }
+                }
+            }
+
+            __fn_bitflags! {
+                /// Returns the set containing all flags.
+                #[inline]
+                pub const fn all() -> $BitFlags {
+                    // See `Debug::fmt` for why this approach is taken.
+                    #[allow(non_snake_case)]
+                    trait __BitFlags {
+                        $(
+                            #[inline]
+                            const $Flag: $T = 0;
+                        )+
+                    }
+                    impl __BitFlags for $BitFlags {
+                        $(
+                            __impl_bitflags! {
+                                #[allow(deprecated)]
+                                #[inline]
+                                $(? #[$attr $($args)*])*
+                                const $Flag: $T = Self::$Flag.bits;
+                            }
+                        )+
+                    }
+                    $BitFlags { bits: $(<$BitFlags as __BitFlags>::$Flag)|+ }
+                }
+            }
+
+            __fn_bitflags! {
+                /// Returns the raw value of the flags currently stored.
+                #[inline]
+                pub const fn bits(&self) -> $T {
+                    self.bits
+                }
+            }
+
+            /// Convert from underlying bit representation, unless that
+            /// representation contains bits that do not correspond to a flag.
+            #[inline]
+            pub fn from_bits(bits: $T) -> $crate::_core::option::Option<$BitFlags> {
+                if (bits & !$BitFlags::all().bits()) == 0 {
+                    $crate::_core::option::Option::Some($BitFlags { bits })
+                } else {
+                    $crate::_core::option::Option::None
+                }
+            }
+
+            __fn_bitflags! {
+                /// Convert from underlying bit representation, dropping any bits
+                /// that do not correspond to flags.
+                #[inline]
+                pub const fn from_bits_truncate(bits: $T) -> $BitFlags {
+                    $BitFlags { bits: bits & $BitFlags::all().bits }
+                }
+            }
+
+            __fn_bitflags! {
+                /// Convert from underlying bit representation, preserving all
+                /// bits (even those not corresponding to a defined flag).
+                #[inline]
+                pub const unsafe fn from_bits_unchecked(bits: $T) -> $BitFlags {
+                    $BitFlags { bits }
+                }
+            }
+
+            __fn_bitflags! {
+                /// Returns `true` if no flags are currently stored.
+                #[inline]
+                pub const fn is_empty(&self) -> bool {
+                    self.bits() == $BitFlags::empty().bits()
+                }
+            }
+
+            __fn_bitflags! {
+                /// Returns `true` if all flags are currently set.
+                #[inline]
+                pub const fn is_all(&self) -> bool {
+                    self.bits == $BitFlags::all().bits
+                }
+            }
+
+            __fn_bitflags! {
+                /// Returns `true` if there are flags common to both `self` and `other`.
+                #[inline]
+                pub const fn intersects(&self, other: $BitFlags) -> bool {
+                    !$BitFlags{ bits: self.bits & other.bits}.is_empty()
+                }
+            }
+
+            __fn_bitflags! {
+                /// Returns `true` all of the flags in `other` are contained within `self`.
+                #[inline]
+                pub const fn contains(&self, other: $BitFlags) -> bool {
+                    (self.bits & other.bits) == other.bits
+                }
+            }
+
+            /// Inserts the specified flags in-place.
+            #[inline]
+            pub fn insert(&mut self, other: $BitFlags) {
+                self.bits |= other.bits;
+            }
+
+            /// Removes the specified flags in-place.
+            #[inline]
+            pub fn remove(&mut self, other: $BitFlags) {
+                self.bits &= !other.bits;
+            }
+
+            /// Toggles the specified flags in-place.
+            #[inline]
+            pub fn toggle(&mut self, other: $BitFlags) {
+                self.bits ^= other.bits;
+            }
+
+            /// Inserts or removes the specified flags depending on the passed value.
+            #[inline]
+            pub fn set(&mut self, other: $BitFlags, value: bool) {
+                if value {
+                    self.insert(other);
+                } else {
+                    self.remove(other);
+                }
+            }
+        }
+
+        impl $crate::_core::ops::BitOr for $BitFlags {
+            type Output = $BitFlags;
+
+            /// Returns the union of the two sets of flags.
+            #[inline]
+            fn bitor(self, other: $BitFlags) -> $BitFlags {
+                $BitFlags { bits: self.bits | other.bits }
+            }
+        }
+
+        impl $crate::_core::ops::BitOrAssign for $BitFlags {
+
+            /// Adds the set of flags.
+            #[inline]
+            fn bitor_assign(&mut self, other: $BitFlags) {
+                self.bits |= other.bits;
+            }
+        }
+
+        impl $crate::_core::ops::BitXor for $BitFlags {
+            type Output = $BitFlags;
+
+            /// Returns the left flags, but with all the right flags toggled.
+            #[inline]
+            fn bitxor(self, other: $BitFlags) -> $BitFlags {
+                $BitFlags { bits: self.bits ^ other.bits }
+            }
+        }
+
+        impl $crate::_core::ops::BitXorAssign for $BitFlags {
+
+            /// Toggles the set of flags.
+            #[inline]
+            fn bitxor_assign(&mut self, other: $BitFlags) {
+                self.bits ^= other.bits;
+            }
+        }
+
+        impl $crate::_core::ops::BitAnd for $BitFlags {
+            type Output = $BitFlags;
+
+            /// Returns the intersection between the two sets of flags.
+            #[inline]
+            fn bitand(self, other: $BitFlags) -> $BitFlags {
+                $BitFlags { bits: self.bits & other.bits }
+            }
+        }
+
+        impl $crate::_core::ops::BitAndAssign for $BitFlags {
+
+            /// Disables all flags disabled in the set.
+            #[inline]
+            fn bitand_assign(&mut self, other: $BitFlags) {
+                self.bits &= other.bits;
+            }
+        }
+
+        impl $crate::_core::ops::Sub for $BitFlags {
+            type Output = $BitFlags;
+
+            /// Returns the set difference of the two sets of flags.
+            #[inline]
+            fn sub(self, other: $BitFlags) -> $BitFlags {
+                $BitFlags { bits: self.bits & !other.bits }
+            }
+        }
+
+        impl $crate::_core::ops::SubAssign for $BitFlags {
+
+            /// Disables all flags enabled in the set.
+            #[inline]
+            fn sub_assign(&mut self, other: $BitFlags) {
+                self.bits &= !other.bits;
+            }
+        }
+
+        impl $crate::_core::ops::Not for $BitFlags {
+            type Output = $BitFlags;
+
+            /// Returns the complement of this set of flags.
+            #[inline]
+            fn not(self) -> $BitFlags {
+                $BitFlags { bits: !self.bits } & $BitFlags::all()
+            }
+        }
+
+        impl $crate::_core::iter::Extend<$BitFlags> for $BitFlags {
+            fn extend<T: $crate::_core::iter::IntoIterator<Item=$BitFlags>>(&mut self, iterator: T) {
+                for item in iterator {
+                    self.insert(item)
+                }
+            }
+        }
+
+        impl $crate::_core::iter::FromIterator<$BitFlags> for $BitFlags {
+            fn from_iter<T: $crate::_core::iter::IntoIterator<Item=$BitFlags>>(iterator: T) -> $BitFlags {
+                let mut result = Self::empty();
+                result.extend(iterator);
+                result
+            }
+        }
+    };
+
+    // Every attribute that the user writes on a const is applied to the
+    // corresponding const that we generate, but within the implementation of
+    // Debug and all() we want to ignore everything but #[cfg] attributes. In
+    // particular, including a #[deprecated] attribute on those items would fail
+    // to compile.
+    // https://github.com/bitflags/bitflags/issues/109
+    //
+    // Input:
+    //
+    //     ? #[cfg(feature = "advanced")]
+    //     ? #[deprecated(note = "Use somthing else.")]
+    //     ? #[doc = r"High quality documentation."]
+    //     fn f() -> i32 { /* ... */ }
+    //
+    // Output:
+    //
+    //     #[cfg(feature = "advanced")]
+    //     fn f() -> i32 { /* ... */ }
+    (
+        $(#[$filtered:meta])*
+        ? #[cfg $($cfgargs:tt)*]
+        $(? #[$rest:ident $($restargs:tt)*])*
+        fn $($item:tt)*
+    ) => {
+        __impl_bitflags! {
+            $(#[$filtered])*
+            #[cfg $($cfgargs)*]
+            $(? #[$rest $($restargs)*])*
+            fn $($item)*
+        }
+    };
+    (
+        $(#[$filtered:meta])*
+        // $next != `cfg`
+        ? #[$next:ident $($nextargs:tt)*]
+        $(? #[$rest:ident $($restargs:tt)*])*
+        fn $($item:tt)*
+    ) => {
+        __impl_bitflags! {
+            $(#[$filtered])*
+            // $next filtered out
+            $(? #[$rest $($restargs)*])*
+            fn $($item)*
+        }
+    };
+    (
+        $(#[$filtered:meta])*
+        fn $($item:tt)*
+    ) => {
+        $(#[$filtered])*
+        fn $($item)*
+    };
+
+    // Every attribute that the user writes on a const is applied to the
+    // corresponding const that we generate, but within the implementation of
+    // Debug and all() we want to ignore everything but #[cfg] attributes. In
+    // particular, including a #[deprecated] attribute on those items would fail
+    // to compile.
+    // https://github.com/bitflags/bitflags/issues/109
+    //
+    // const version
+    //
+    // Input:
+    //
+    //     ? #[cfg(feature = "advanced")]
+    //     ? #[deprecated(note = "Use somthing else.")]
+    //     ? #[doc = r"High quality documentation."]
+    //     const f: i32 { /* ... */ }
+    //
+    // Output:
+    //
+    //     #[cfg(feature = "advanced")]
+    //     const f: i32 { /* ... */ }
+    (
+        $(#[$filtered:meta])*
+        ? #[cfg $($cfgargs:tt)*]
+        $(? #[$rest:ident $($restargs:tt)*])*
+        const $($item:tt)*
+    ) => {
+        __impl_bitflags! {
+            $(#[$filtered])*
+            #[cfg $($cfgargs)*]
+            $(? #[$rest $($restargs)*])*
+            const $($item)*
+        }
+    };
+    (
+        $(#[$filtered:meta])*
+        // $next != `cfg`
+        ? #[$next:ident $($nextargs:tt)*]
+        $(? #[$rest:ident $($restargs:tt)*])*
+        const $($item:tt)*
+    ) => {
+        __impl_bitflags! {
+            $(#[$filtered])*
+            // $next filtered out
+            $(? #[$rest $($restargs)*])*
+            const $($item)*
+        }
+    };
+    (
+        $(#[$filtered:meta])*
+        const $($item:tt)*
+    ) => {
+        $(#[$filtered])*
+        const $($item)*
+    };
+}
+
+// Same as std::stringify but callable from __impl_bitflags, which needs to use
+// local_inner_macros so can only directly call macros from this crate.
+#[macro_export]
+#[doc(hidden)]
+macro_rules! __bitflags_stringify {
+    ($s:ident) => {
+        stringify!($s)
+    };
+}
+
+#[cfg(feature = "example_generated")]
+pub mod example_generated;
+
+#[cfg(test)]
+mod tests {
+    use std::collections::hash_map::DefaultHasher;
+    use std::hash::{Hash, Hasher};
+
+    bitflags! {
+        #[doc = "> The first principle is that you must not fool yourself — and"]
+        #[doc = "> you are the easiest person to fool."]
+        #[doc = "> "]
+        #[doc = "> - Richard Feynman"]
+        struct Flags: u32 {
+            const A = 0b00000001;
+            #[doc = "<pcwalton> macros are way better at generating code than trans is"]
+            const B = 0b00000010;
+            const C = 0b00000100;
+            #[doc = "* cmr bed"]
+            #[doc = "* strcat table"]
+            #[doc = "<strcat> wait what?"]
+            const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
+        }
+    }
+
+    bitflags! {
+        struct _CfgFlags: u32 {
+            #[cfg(unix)]
+            const _CFG_A = 0b01;
+            #[cfg(windows)]
+            const _CFG_B = 0b01;
+            #[cfg(unix)]
+            const _CFG_C = Self::_CFG_A.bits | 0b10;
+        }
+    }
+
+    bitflags! {
+        struct AnotherSetOfFlags: i8 {
+            const ANOTHER_FLAG = -1_i8;
+        }
+    }
+
+    bitflags! {
+        struct LongFlags: u32 {
+            const LONG_A = 0b1111111111111111;
+        }
+    }
+
+    #[test]
+    fn test_bits() {
+        assert_eq!(Flags::empty().bits(), 0b00000000);
+        assert_eq!(Flags::A.bits(), 0b00000001);
+        assert_eq!(Flags::ABC.bits(), 0b00000111);
+
+        assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00);
+        assert_eq!(AnotherSetOfFlags::ANOTHER_FLAG.bits(), !0_i8);
+    }
+
+    #[test]
+    fn test_from_bits() {
+        assert_eq!(Flags::from_bits(0), Some(Flags::empty()));
+        assert_eq!(Flags::from_bits(0b1), Some(Flags::A));
+        assert_eq!(Flags::from_bits(0b10), Some(Flags::B));
+        assert_eq!(Flags::from_bits(0b11), Some(Flags::A | Flags::B));
+        assert_eq!(Flags::from_bits(0b1000), None);
+
+        assert_eq!(
+            AnotherSetOfFlags::from_bits(!0_i8),
+            Some(AnotherSetOfFlags::ANOTHER_FLAG)
+        );
+    }
+
+    #[test]
+    fn test_from_bits_truncate() {
+        assert_eq!(Flags::from_bits_truncate(0), Flags::empty());
+        assert_eq!(Flags::from_bits_truncate(0b1), Flags::A);
+        assert_eq!(Flags::from_bits_truncate(0b10), Flags::B);
+        assert_eq!(Flags::from_bits_truncate(0b11), (Flags::A | Flags::B));
+        assert_eq!(Flags::from_bits_truncate(0b1000), Flags::empty());
+        assert_eq!(Flags::from_bits_truncate(0b1001), Flags::A);
+
+        assert_eq!(
+            AnotherSetOfFlags::from_bits_truncate(0_i8),
+            AnotherSetOfFlags::empty()
+        );
+    }
+
+    #[test]
+    fn test_from_bits_unchecked() {
+        let extra = unsafe { Flags::from_bits_unchecked(0b1000) };
+        assert_eq!(unsafe { Flags::from_bits_unchecked(0) }, Flags::empty());
+        assert_eq!(unsafe { Flags::from_bits_unchecked(0b1) }, Flags::A);
+        assert_eq!(unsafe { Flags::from_bits_unchecked(0b10) }, Flags::B);
+        assert_eq!(unsafe { Flags::from_bits_unchecked(0b11) }, (Flags::A | Flags::B));
+        assert_eq!(unsafe { Flags::from_bits_unchecked(0b1000) }, (extra | Flags::empty()));
+        assert_eq!(unsafe { Flags::from_bits_unchecked(0b1001) }, (extra | Flags::A));
+    }
+
+    #[test]
+    fn test_is_empty() {
+        assert!(Flags::empty().is_empty());
+        assert!(!Flags::A.is_empty());
+        assert!(!Flags::ABC.is_empty());
+
+        assert!(!AnotherSetOfFlags::ANOTHER_FLAG.is_empty());
+    }
+
+    #[test]
+    fn test_is_all() {
+        assert!(Flags::all().is_all());
+        assert!(!Flags::A.is_all());
+        assert!(Flags::ABC.is_all());
+
+        assert!(AnotherSetOfFlags::ANOTHER_FLAG.is_all());
+    }
+
+    #[test]
+    fn test_two_empties_do_not_intersect() {
+        let e1 = Flags::empty();
+        let e2 = Flags::empty();
+        assert!(!e1.intersects(e2));
+
+        assert!(AnotherSetOfFlags::ANOTHER_FLAG.intersects(AnotherSetOfFlags::ANOTHER_FLAG));
+    }
+
+    #[test]
+    fn test_empty_does_not_intersect_with_full() {
+        let e1 = Flags::empty();
+        let e2 = Flags::ABC;
+        assert!(!e1.intersects(e2));
+    }
+
+    #[test]
+    fn test_disjoint_intersects() {
+        let e1 = Flags::A;
+        let e2 = Flags::B;
+        assert!(!e1.intersects(e2));
+    }
+
+    #[test]
+    fn test_overlapping_intersects() {
+        let e1 = Flags::A;
+        let e2 = Flags::A | Flags::B;
+        assert!(e1.intersects(e2));
+    }
+
+    #[test]
+    fn test_contains() {
+        let e1 = Flags::A;
+        let e2 = Flags::A | Flags::B;
+        assert!(!e1.contains(e2));
+        assert!(e2.contains(e1));
+        assert!(Flags::ABC.contains(e2));
+
+        assert!(AnotherSetOfFlags::ANOTHER_FLAG.contains(AnotherSetOfFlags::ANOTHER_FLAG));
+    }
+
+    #[test]
+    fn test_insert() {
+        let mut e1 = Flags::A;
+        let e2 = Flags::A | Flags::B;
+        e1.insert(e2);
+        assert_eq!(e1, e2);
+
+        let mut e3 = AnotherSetOfFlags::empty();
+        e3.insert(AnotherSetOfFlags::ANOTHER_FLAG);
+        assert_eq!(e3, AnotherSetOfFlags::ANOTHER_FLAG);
+    }
+
+    #[test]
+    fn test_remove() {
+        let mut e1 = Flags::A | Flags::B;
+        let e2 = Flags::A | Flags::C;
+        e1.remove(e2);
+        assert_eq!(e1, Flags::B);
+
+        let mut e3 = AnotherSetOfFlags::ANOTHER_FLAG;
+        e3.remove(AnotherSetOfFlags::ANOTHER_FLAG);
+        assert_eq!(e3, AnotherSetOfFlags::empty());
+    }
+
+    #[test]
+    fn test_operators() {
+        let e1 = Flags::A | Flags::C;
+        let e2 = Flags::B | Flags::C;
+        assert_eq!((e1 | e2), Flags::ABC); // union
+        assert_eq!((e1 & e2), Flags::C); // intersection
+        assert_eq!((e1 - e2), Flags::A); // set difference
+        assert_eq!(!e2, Flags::A); // set complement
+        assert_eq!(e1 ^ e2, Flags::A | Flags::B); // toggle
+        let mut e3 = e1;
+        e3.toggle(e2);
+        assert_eq!(e3, Flags::A | Flags::B);
+
+        let mut m4 = AnotherSetOfFlags::empty();
+        m4.toggle(AnotherSetOfFlags::empty());
+        assert_eq!(m4, AnotherSetOfFlags::empty());
+    }
+
+    #[test]
+    fn test_operators_unchecked() {
+        let extra = unsafe { Flags::from_bits_unchecked(0b1000) };
+        let e1 = Flags::A | Flags::C | extra;
+        let e2 = Flags::B | Flags::C;
+        assert_eq!((e1 | e2), (Flags::ABC | extra)); // union
+        assert_eq!((e1 & e2), Flags::C); // intersection
+        assert_eq!((e1 - e2), (Flags::A | extra)); // set difference
+        assert_eq!(!e2, Flags::A); // set complement
+        assert_eq!(!e1, Flags::B); // set complement
+        assert_eq!(e1 ^ e2, Flags::A | Flags::B | extra); // toggle
+        let mut e3 = e1;
+        e3.toggle(e2);
+        assert_eq!(e3, Flags::A | Flags::B | extra);
+    }
+
+    #[test]
+    fn test_set() {
+        let mut e1 = Flags::A | Flags::C;
+        e1.set(Flags::B, true);
+        e1.set(Flags::C, false);
+
+        assert_eq!(e1, Flags::A | Flags::B);
+    }
+
+    #[test]
+    fn test_assignment_operators() {
+        let mut m1 = Flags::empty();
+        let e1 = Flags::A | Flags::C;
+        // union
+        m1 |= Flags::A;
+        assert_eq!(m1, Flags::A);
+        // intersection
+        m1 &= e1;
+        assert_eq!(m1, Flags::A);
+        // set difference
+        m1 -= m1;
+        assert_eq!(m1, Flags::empty());
+        // toggle
+        m1 ^= e1;
+        assert_eq!(m1, e1);
+    }
+
+
+    #[cfg(bitflags_const_fn)]
+    #[test]
+    fn test_const_fn() {
+        const _M1: Flags = Flags::empty();
+
+        const M2: Flags = Flags::A;
+        assert_eq!(M2, Flags::A);
+
+        const M3: Flags = Flags::C;
+        assert_eq!(M3, Flags::C);
+    }
+
+    #[test]
+    fn test_extend() {
+        let mut flags;
+
+        flags = Flags::empty();
+        flags.extend([].iter().cloned());
+        assert_eq!(flags, Flags::empty());
+
+        flags = Flags::empty();
+        flags.extend([Flags::A, Flags::B].iter().cloned());
+        assert_eq!(flags, Flags::A | Flags::B);
+
+        flags = Flags::A;
+        flags.extend([Flags::A, Flags::B].iter().cloned());
+        assert_eq!(flags, Flags::A | Flags::B);
+
+        flags = Flags::B;
+        flags.extend([Flags::A, Flags::ABC].iter().cloned());
+        assert_eq!(flags, Flags::ABC);
+    }
+
+    #[test]
+    fn test_from_iterator() {
+        assert_eq!([].iter().cloned().collect::<Flags>(), Flags::empty());
+        assert_eq!(
+            [Flags::A, Flags::B].iter().cloned().collect::<Flags>(),
+            Flags::A | Flags::B
+        );
+        assert_eq!(
+            [Flags::A, Flags::ABC].iter().cloned().collect::<Flags>(),
+            Flags::ABC
+        );
+    }
+
+    #[test]
+    fn test_lt() {
+        let mut a = Flags::empty();
+        let mut b = Flags::empty();
+
+        assert!(!(a < b) && !(b < a));
+        b = Flags::B;
+        assert!(a < b);
+        a = Flags::C;
+        assert!(!(a < b) && b < a);
+        b = Flags::C | Flags::B;
+        assert!(a < b);
+    }
+
+    #[test]
+    fn test_ord() {
+        let mut a = Flags::empty();
+        let mut b = Flags::empty();
+
+        assert!(a <= b && a >= b);
+        a = Flags::A;
+        assert!(a > b && a >= b);
+        assert!(b < a && b <= a);
+        b = Flags::B;
+        assert!(b > a && b >= a);
+        assert!(a < b && a <= b);
+    }
+
+    fn hash<T: Hash>(t: &T) -> u64 {
+        let mut s = DefaultHasher::new();
+        t.hash(&mut s);
+        s.finish()
+    }
+
+    #[test]
+    fn test_hash() {
+        let mut x = Flags::empty();
+        let mut y = Flags::empty();
+        assert_eq!(hash(&x), hash(&y));
+        x = Flags::all();
+        y = Flags::ABC;
+        assert_eq!(hash(&x), hash(&y));
+    }
+
+    #[test]
+    fn test_debug() {
+        assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B");
+        assert_eq!(format!("{:?}", Flags::empty()), "(empty)");
+        assert_eq!(format!("{:?}", Flags::ABC), "A | B | C | ABC");
+        let extra = unsafe { Flags::from_bits_unchecked(0xb8) };
+        assert_eq!(format!("{:?}", extra), "0xb8");
+        assert_eq!(format!("{:?}", Flags::A | extra), "A | 0xb8");
+        assert_eq!(format!("{:?}", Flags::ABC | extra), "A | B | C | ABC | 0xb8");
+    }
+
+    #[test]
+    fn test_binary() {
+        assert_eq!(format!("{:b}", Flags::ABC), "111");
+        assert_eq!(format!("{:#b}", Flags::ABC), "0b111");
+        let extra = unsafe { Flags::from_bits_unchecked(0b1010000) };
+        assert_eq!(format!("{:b}", Flags::ABC | extra), "1010111");
+        assert_eq!(format!("{:#b}", Flags::ABC | extra), "0b1010111");
+    }
+
+    #[test]
+    fn test_octal() {
+        assert_eq!(format!("{:o}", LongFlags::LONG_A), "177777");
+        assert_eq!(format!("{:#o}", LongFlags::LONG_A), "0o177777");
+        let extra = unsafe { LongFlags::from_bits_unchecked(0o5000000) };
+        assert_eq!(format!("{:o}", LongFlags::LONG_A | extra), "5177777");
+        assert_eq!(format!("{:#o}", LongFlags::LONG_A | extra), "0o5177777");
+    }
+
+    #[test]
+    fn test_lowerhex() {
+        assert_eq!(format!("{:x}", LongFlags::LONG_A), "ffff");
+        assert_eq!(format!("{:#x}", LongFlags::LONG_A), "0xffff");
+        let extra = unsafe { LongFlags::from_bits_unchecked(0xe00000) };
+        assert_eq!(format!("{:x}", LongFlags::LONG_A | extra), "e0ffff");
+        assert_eq!(format!("{:#x}", LongFlags::LONG_A | extra), "0xe0ffff");
+    }
+
+    #[test]
+    fn test_upperhex() {
+        assert_eq!(format!("{:X}", LongFlags::LONG_A), "FFFF");
+        assert_eq!(format!("{:#X}", LongFlags::LONG_A), "0xFFFF");
+        let extra = unsafe { LongFlags::from_bits_unchecked(0xe00000) };
+        assert_eq!(format!("{:X}", LongFlags::LONG_A | extra), "E0FFFF");
+        assert_eq!(format!("{:#X}", LongFlags::LONG_A | extra), "0xE0FFFF");
+    }
+
+    mod submodule {
+        bitflags! {
+            pub struct PublicFlags: i8 {
+                const X = 0;
+            }
+        }
+        bitflags! {
+            struct PrivateFlags: i8 {
+                const Y = 0;
+            }
+        }
+
+        #[test]
+        fn test_private() {
+            let _ = PrivateFlags::Y;
+        }
+    }
+
+    #[test]
+    fn test_public() {
+        let _ = submodule::PublicFlags::X;
+    }
+
+    mod t1 {
+        mod foo {
+            pub type Bar = i32;
+        }
+
+        bitflags! {
+            /// baz
+            struct Flags: foo::Bar {
+                const A = 0b00000001;
+                #[cfg(foo)]
+                const B = 0b00000010;
+                #[cfg(foo)]
+                const C = 0b00000010;
+            }
+        }
+    }
+
+    #[test]
+    fn test_in_function() {
+        bitflags! {
+           struct Flags: u8 {
+                const A = 1;
+                #[cfg(any())] // false
+                const B = 2;
+            }
+        }
+        assert_eq!(Flags::all(), Flags::A);
+        assert_eq!(format!("{:?}", Flags::A), "A");
+    }
+
+    #[test]
+    fn test_deprecated() {
+        bitflags! {
+            pub struct TestFlags: u32 {
+                #[deprecated(note = "Use something else.")]
+                const ONE = 1;
+            }
+        }
+    }
+
+    #[test]
+    fn test_pub_crate() {
+        mod module {
+            bitflags! {
+                pub (crate) struct Test: u8 {
+                    const FOO = 1;
+                }
+            }
+        }
+
+        assert_eq!(module::Test::FOO.bits(), 1);
+    }
+
+    #[test]
+    fn test_pub_in_module() {
+        mod module {
+            mod submodule {
+                bitflags! {
+                    // `pub (in super)` means only the module `module` will
+                    // be able to access this.
+                    pub (in super) struct Test: u8 {
+                        const FOO = 1;
+                    }
+                }
+            }
+
+            mod test {
+                // Note: due to `pub (in super)`,
+                // this cannot be accessed directly by the testing code.
+                pub(super) fn value() -> u8 {
+                    super::submodule::Test::FOO.bits()
+                }
+            }
+
+            pub fn value() -> u8 {
+                test::value()
+            }
+        }
+
+        assert_eq!(module::value(), 1)
+    }
+
+    #[test]
+    fn test_zero_value_flags() {
+        bitflags! {
+            struct Flags: u32 {
+                const NONE = 0b0;
+                const SOME = 0b1;
+            }
+        }
+
+        assert!(Flags::empty().contains(Flags::NONE));
+        assert!(Flags::SOME.contains(Flags::NONE));
+        assert!(Flags::NONE.is_empty());
+
+        assert_eq!(format!("{:?}", Flags::empty()), "NONE");
+        assert_eq!(format!("{:?}", Flags::SOME), "SOME");
+    }
+}
--- a/third_party/rust/cubeb-backend/.cargo-checksum.json
+++ b/third_party/rust/cubeb-backend/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"4e854a5f7f2314ebf97a191a7de46c3e0e4264f5e8f5d48e41008201dd79f48e","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","src/capi.rs":"2dafb53cf87041aea0ebe37fc38eac9653fa8382300df68ab51893fd1fe5614a","src/lib.rs":"94b80747ae1037423a2281f2572fc6d15cd7702417974ae3730adccd71c7a300","src/log.rs":"704faeb31934dad6bc6d02e01caa85118754209bd559d30d03fcfa5cb8c1603c","src/ops.rs":"55cbf9bdccdd854834eba72e8bde3e59a9a4193e65209769a1a6e0d8a320b8f6","src/traits.rs":"60bbb1b756e1576a691037e159f939e06b6d32c84b681cb6a1d0eaffd5205ae4","tests/test_capi.rs":"9d949cbdb1c19e229ce4f652999a058c283cf7d5a882a669dbca08b71ac2fb62"},"package":"54c14a298d865c7f454dd809b2feb1fdb361b0a143f8ed2ea0b3a9becfa0a2ea"}
\ No newline at end of file
+{"files":{"Cargo.toml":"de46790fd917de4acfb50889d759e7be0d562b00e4169711946a38ea96973b38","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","src/capi.rs":"faec78d41430ae26ac24b46d5833c76f94ac6eebb4b2186383ebb5e9de32cf8f","src/lib.rs":"94b80747ae1037423a2281f2572fc6d15cd7702417974ae3730adccd71c7a300","src/log.rs":"704faeb31934dad6bc6d02e01caa85118754209bd559d30d03fcfa5cb8c1603c","src/ops.rs":"d9465abd16c2ce7414aecfc8f983fc9c29dc9b4780c0ea2074974a9814653576","src/traits.rs":"fa8463bd030c1d7716b05401fd2425ff0a399ee0c4dacfeed22341d89ecad871","tests/test_capi.rs":"25860adff6e9e2bcb06371f1e7e52e5f8a20c61fd6b2efe61b7713f3bc4f1031"},"package":"5a1e7add4e7642a8aebb24172922318482bed52389a12cb339f728bbd4c4ed9c"}
\ No newline at end of file
--- a/third_party/rust/cubeb-backend/Cargo.toml
+++ b/third_party/rust/cubeb-backend/Cargo.toml
@@ -7,23 +7,23 @@
 #
 # 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 = "cubeb-backend"
-version = "0.5.5"
+version = "0.6.2"
 authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"]
 description = "Bindings to libcubeb internals to facilitate implementing cubeb backends in rust.\n"
 homepage = "https://github.com/djg/cubeb-rs"
 keywords = ["cubeb"]
 categories = ["api-bindings"]
 license = "ISC"
 repository = "https://github.com/djg/cubeb-rs"
 [dependencies.cubeb-core]
-version = "0.5.5"
+version = "0.6.2"
 
 [features]
 gecko-in-tree = ["cubeb-core/gecko-in-tree"]
 [badges.circle-ci]
 repository = "djg/cubeb-rs"
--- a/third_party/rust/cubeb-backend/src/capi.rs
+++ b/third_party/rust/cubeb-backend/src/capi.rs
@@ -45,17 +45,16 @@ macro_rules! capi_new(
             stream_destroy: Some($crate::capi::capi_stream_destroy::<$stm>),
             stream_start: Some($crate::capi::capi_stream_start::<$stm>),
             stream_stop: Some($crate::capi::capi_stream_stop::<$stm>),
             stream_reset_default_device:
                 Some($crate::capi::capi_stream_reset_default_device::<$stm>),
             stream_get_position: Some($crate::capi::capi_stream_get_position::<$stm>),
             stream_get_latency: Some($crate::capi::capi_stream_get_latency::<$stm>),
             stream_set_volume: Some($crate::capi::capi_stream_set_volume::<$stm>),
-            stream_set_panning: Some($crate::capi::capi_stream_set_panning::<$stm>),
             stream_get_current_device: Some($crate::capi::capi_stream_get_current_device::<$stm>),
             stream_device_destroy: Some($crate::capi::capi_stream_device_destroy::<$stm>),
             stream_register_device_changed_callback:
                 Some($crate::capi::capi_stream_register_device_changed_callback::<$stm>),
             register_device_collection_changed:
                 Some($crate::capi::capi_register_device_collection_changed::<$ctx>)
         }));
 
@@ -222,26 +221,16 @@ pub unsafe extern "C" fn capi_stream_set
     volume: f32,
 ) -> c_int {
     let stm = &mut *(s as *mut STM);
 
     _try!(stm.set_volume(volume));
     ffi::CUBEB_OK
 }
 
-pub unsafe extern "C" fn capi_stream_set_panning<STM: StreamOps>(
-    s: *mut ffi::cubeb_stream,
-    panning: f32,
-) -> c_int {
-    let stm = &mut *(s as *mut STM);
-
-    _try!(stm.set_panning(panning));
-    ffi::CUBEB_OK
-}
-
 pub unsafe extern "C" fn capi_stream_get_current_device<STM: StreamOps>(
     s: *mut ffi::cubeb_stream,
     device: *mut *mut ffi::cubeb_device,
 ) -> i32 {
     let stm = &mut *(s as *mut STM);
 
     *device = _try!(stm.current_device()).as_ptr();
     ffi::CUBEB_OK
--- a/third_party/rust/cubeb-backend/src/ops.rs
+++ b/third_party/rust/cubeb-backend/src/ops.rs
@@ -60,18 +60,16 @@ pub struct Ops {
     pub stream_reset_default_device:
         Option<unsafe extern "C" fn(stream: *mut ffi::cubeb_stream) -> c_int>,
     pub stream_get_position:
         Option<unsafe extern "C" fn(stream: *mut ffi::cubeb_stream, position: *mut u64) -> c_int>,
     pub stream_get_latency:
         Option<unsafe extern "C" fn(stream: *mut ffi::cubeb_stream, latency: *mut u32) -> c_int>,
     pub stream_set_volume:
         Option<unsafe extern "C" fn(stream: *mut ffi::cubeb_stream, volumes: c_float) -> c_int>,
-    pub stream_set_panning:
-        Option<unsafe extern "C" fn(stream: *mut ffi::cubeb_stream, panning: c_float) -> c_int>,
     pub stream_get_current_device: Option<
         unsafe extern "C" fn(stream: *mut ffi::cubeb_stream, device: *mut *mut ffi::cubeb_device)
             -> c_int,
     >,
     pub stream_device_destroy: Option<
         unsafe extern "C" fn(stream: *mut ffi::cubeb_stream, device: *mut ffi::cubeb_device)
             -> c_int,
     >,
--- a/third_party/rust/cubeb-backend/src/traits.rs
+++ b/third_party/rust/cubeb-backend/src/traits.rs
@@ -44,16 +44,15 @@ pub trait ContextOps {
 
 pub trait StreamOps {
     fn start(&mut self) -> Result<()>;
     fn stop(&mut self) -> Result<()>;
     fn reset_default_device(&mut self) -> Result<()>;
     fn position(&mut self) -> Result<u64>;
     fn latency(&mut self) -> Result<u32>;
     fn set_volume(&mut self, volume: f32) -> Result<()>;
-    fn set_panning(&mut self, panning: f32) -> Result<()>;
     fn current_device(&mut self) -> Result<&DeviceRef>;
     fn device_destroy(&mut self, device: &DeviceRef) -> Result<()>;
     fn register_device_changed_callback(
         &mut self,
         device_changed_callback: ffi::cubeb_device_changed_callback,
     ) -> Result<()>;
 }
--- a/third_party/rust/cubeb-backend/tests/test_capi.rs
+++ b/third_party/rust/cubeb-backend/tests/test_capi.rs
@@ -99,20 +99,16 @@ impl StreamOps for TestStream {
     }
     fn latency(&mut self) -> Result<u32> {
         Ok(0u32)
     }
     fn set_volume(&mut self, volume: f32) -> Result<()> {
         assert_eq!(volume, 0.5);
         Ok(())
     }
-    fn set_panning(&mut self, panning: f32) -> Result<()> {
-        assert_eq!(panning, 0.5);
-        Ok(())
-    }
     fn current_device(&mut self) -> Result<&DeviceRef> {
         Ok(unsafe { DeviceRef::from_ptr(0xDEAD_BEEF as *mut _) })
     }
     fn device_destroy(&mut self, device: &DeviceRef) -> Result<()> {
         assert_eq!(device.as_ptr(), 0xDEAD_BEEF as *mut _);
         Ok(())
     }
     fn register_device_changed_callback(
@@ -218,24 +214,16 @@ fn test_ops_stream_latency() {
 fn test_ops_stream_set_volume() {
     let s: *mut ffi::cubeb_stream = ptr::null_mut();
     unsafe {
         OPS.stream_set_volume.unwrap()(s, 0.5);
     }
 }
 
 #[test]
-fn test_ops_stream_set_panning() {
-    let s: *mut ffi::cubeb_stream = ptr::null_mut();
-    unsafe {
-        OPS.stream_set_panning.unwrap()(s, 0.5);
-    }
-}
-
-#[test]
 fn test_ops_stream_current_device() {
     let s: *mut ffi::cubeb_stream = ptr::null_mut();
     let mut device: *mut ffi::cubeb_device = ptr::null_mut();
     assert_eq!(
         unsafe { OPS.stream_get_current_device.unwrap()(s, &mut device) },
         ffi::CUBEB_OK
     );
     assert_eq!(device, 0xDEAD_BEEF as *mut _);
--- a/third_party/rust/cubeb-core/.cargo-checksum.json
+++ b/third_party/rust/cubeb-core/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"f0fc91e3408113b5fcf54fda6ec59639f4501f083e6b17b7b1eecd9689e30502","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","src/builders.rs":"ca97e3a3d1f3fc451c17851c8538964ec67f3964dfe29e902d904ee7445becca","src/channel.rs":"c8d5a76ef3ecdd96cd4de516e3d4d139bbb83c4690d1c3f5fd07fffc47be51f1","src/context.rs":"09625b75070ec88d566a907ab2e574e2d85df4c6df295f798b3372df2cdc8f7a","src/device.rs":"490d2e94ecae1e149476c2e8d9aa03c4163987c3efccc962b2d3123e4c09dedf","src/device_collection.rs":"f6d0c1628cc34b524f86b84a1e1c79971c3f64ebc4ac64eeb10a1330bbe8c238","src/error.rs":"855ff3d3597753f832ecea00e403c71129afd80db3d39456cf3e23cb9aeb91e7","src/ffi_types.rs":"d815d7a80895b5e86907e708dc0219fca4ac4668cde114afee434e7d702a145d","src/format.rs":"5513c537a72af1c222ee7c30b26d4de9d368a69772688b95d88b1a99f6892d5c","src/lib.rs":"6010a5e20b836b8e5c9fba382fde819e6f3c18c0ec2016e6e7e118eabedbcd51","src/log.rs":"c46bae3472043fd076df3229c3421d948a87fae8495c1524b41ab2d8608f612a","src/stream.rs":"95b8665fc860971250c28e7eba1f02759e83fdb8bae0b4ac7b615336cb87f758","src/try_call.rs":"231bfa3f3448f7531427bb228beb2bcd4fd711f0b13d2d8f412af013470f40c7","src/util.rs":"308cfbaacd615ff600e74415c52daeef007fff34a4a0648a73c0042f6067f84f"},"package":"20c6cde72d3505dc4f2452e0378b970b03d1fddf3ad8ac1b98dcb65fc7721907"}
\ No newline at end of file
+{"files":{"Cargo.toml":"12fc57e44d5f3962acec8860191fe0e9aca6ebe654924f4736b35cf15450b0d1","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","src/builders.rs":"ca97e3a3d1f3fc451c17851c8538964ec67f3964dfe29e902d904ee7445becca","src/channel.rs":"c8d5a76ef3ecdd96cd4de516e3d4d139bbb83c4690d1c3f5fd07fffc47be51f1","src/context.rs":"09625b75070ec88d566a907ab2e574e2d85df4c6df295f798b3372df2cdc8f7a","src/device.rs":"490d2e94ecae1e149476c2e8d9aa03c4163987c3efccc962b2d3123e4c09dedf","src/device_collection.rs":"f6d0c1628cc34b524f86b84a1e1c79971c3f64ebc4ac64eeb10a1330bbe8c238","src/error.rs":"855ff3d3597753f832ecea00e403c71129afd80db3d39456cf3e23cb9aeb91e7","src/ffi_types.rs":"d815d7a80895b5e86907e708dc0219fca4ac4668cde114afee434e7d702a145d","src/format.rs":"5513c537a72af1c222ee7c30b26d4de9d368a69772688b95d88b1a99f6892d5c","src/lib.rs":"6010a5e20b836b8e5c9fba382fde819e6f3c18c0ec2016e6e7e118eabedbcd51","src/log.rs":"c46bae3472043fd076df3229c3421d948a87fae8495c1524b41ab2d8608f612a","src/stream.rs":"56de9f3ad372c123932eca23659f76e7b65fc4502c8da5fe91f3ed35666c306d","src/try_call.rs":"231bfa3f3448f7531427bb228beb2bcd4fd711f0b13d2d8f412af013470f40c7","src/util.rs":"308cfbaacd615ff600e74415c52daeef007fff34a4a0648a73c0042f6067f84f"},"package":"bfd9b2ea1cb6afed9419b0d18fc4093df552ccb2300eb57793629f8cd370b4c8"}
\ No newline at end of file
--- a/third_party/rust/cubeb-core/Cargo.toml
+++ b/third_party/rust/cubeb-core/Cargo.toml
@@ -7,26 +7,26 @@
 #
 # 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 = "cubeb-core"
-version = "0.5.5"
+version = "0.6.2"
 authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"]
 description = "Common types and definitions for cubeb rust and C bindings. Not intended for direct use.\n"
 homepage = "https://github.com/djg/cubeb-rs"
 keywords = ["cubeb"]
 categories = ["api-bindings"]
 license = "ISC"
 repository = "https://github.com/djg/cubeb-rs"
 [dependencies.bitflags]
 version = "1.0"
 
 [dependencies.cubeb-sys]
-version = "0.5.5"
+version = "0.6.2"
 
 [features]
 gecko-in-tree = ["cubeb-sys/gecko-in-tree"]
 [badges.circle-ci]
 repository = "djg/cubeb-rs"
--- a/third_party/rust/cubeb-core/src/stream.rs
+++ b/third_party/rust/cubeb-core/src/stream.rs
@@ -143,27 +143,16 @@ impl StreamRef {
         Ok(latency)
     }
 
     /// Set the volume for a stream.
     pub fn set_volume(&self, volume: f32) -> Result<()> {
         unsafe { call!(ffi::cubeb_stream_set_volume(self.as_ptr(), volume)) }
     }
 
-    /// If the stream is stereo, set the left/right panning. If the stream is mono,
-    /// this has no effect.
-    ///
-    /// panning a number from -1.0 to 1.0. -1.0 means that the stream is
-    /// fully mixed in the left channel, 1.0 means the stream is fully
-    /// mixed in the right channel. 0.0 is equal power in the right
-    /// and left channel (default).
-    pub fn set_panning(&self, panning: f32) -> Result<()> {
-        unsafe { call!(ffi::cubeb_stream_set_panning(self.as_ptr(), panning)) }
-    }
-
     /// Get the current output device for this stream.
     pub fn current_device(&self) -> Result<&DeviceRef> {
         let mut device: *mut ffi::cubeb_device = ptr::null_mut();
         unsafe {
             let _ = try_call!(ffi::cubeb_stream_get_current_device(
                 self.as_ptr(),
                 &mut device
             ));
--- a/third_party/rust/cubeb-sys/.cargo-checksum.json
+++ b/third_party/rust/cubeb-sys/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"ed3411a6a717d7a7565cce826b14c7d0071bbce82a5323cc4d5bdaab71696400","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","build.rs":"84f01f6c5f4559b87e348f6bc04d840a405889549dddf5e74cb486ad8b71bef2","libcubeb/AUTHORS":"829e45d138c7c8827799f302806fa4be8cd8bd4bad70a2fe26c3a27a5cf36948","libcubeb/CMakeLists.txt":"e050a0d22384d05452a2e2a4fa774cec0135b149f2b6cc4d5002ac38802a20d2","libcubeb/Config.cmake.in":"88019286c96ef3d5d3a673b183c8655dfc97ceede07d3eb6c18f0c51bb896388","libcubeb/INSTALL.md":"7a84cdfbe86e7d3180e2203603b88571df61b369421fa97ee86740ffd4d4db8e","libcubeb/LICENSE":"44c6b5ae5ec3fe2fbc608b00e6f4896f4d2d5c7e525fcbaa3eaa3cf2f3d5a983","libcubeb/README.md":"aa417156dc65069264901b75fc3c792c73021ec61c909de04e109bd4184c07ab","libcubeb/TODO":"6f8065136e005d2becee810e3d8697a94f2c755f8c79687adfac7136ad165e80","libcubeb/appveyor.yml":"9a87fdc18b76fca1167289ecb2ec3a210b76984c1d7e92268b2cd36f1e00f541","libcubeb/cmake/sanitizers-cmake/CMakeLists.txt":"89b282c19b3897ff666f7847d5e679ae928ca7e76ffd0d23f7c58c9464048b61","libcubeb/cmake/sanitizers-cmake/LICENSE":"4b67e7ae8c91e68e1a929eb1cbaa4c773c6d19aa91aaa12c390cf9560d1c9799","libcubeb/cmake/sanitizers-cmake/README.md":"f3b85a594e1601ae65bb09393c56fbc8a98e3f3f49234e56f86bd78803c3544e","libcubeb/cmake/sanitizers-cmake/cmake/FindASan.cmake":"bd30b1c3cb0682b8a2b0b599f6c51fbf99ef4908b00eba8826f0d484c623b01b","libcubeb/cmake/sanitizers-cmake/cmake/FindMSan.cmake":"55e40f0994b47f8e779622af2007c69252d9456be99f4aa4fba7dd49c23d5580","libcubeb/cmake/sanitizers-cmake/cmake/FindSanitizers.cmake":"2ffd9717a49e3e9de848ec0d91097bdbab3f75a7866211d902f9659f59271ffc","libcubeb/cmake/sanitizers-cmake/cmake/FindTSan.cmake":"ceace234abd5a463ad1b8134ad06c4c8004895b2e8fc9edb67e64620ea97ca47","libcubeb/cmake/sanitizers-cmake/cmake/FindUBSan.cmake":"4720ec96ea42a2a9c07d887c1fc5562ed3e8c222f5778a18b78c46678b23f156","libcubeb/cmake/sanitizers-cmake/cmake/asan-wrapper":"4e543936e6374e24b80a0f92135c07c2e2101c0d110e51bddaf0e70ae8ec391e","libcubeb/cmake/sanitizers-cmake/cmake/sanitize-helpers.cmake":"c0c225f22bebd27eb68b807b2a61962d28afc61609735fe652c2fde6aa6a005b","libcubeb/cmake/sanitizers-cmake/tests/CMakeLists.txt":"64b7aea469a043f27414e3d652aaa89a03a11843d152c4cd42f30561e6ef51bc","libcubeb/cmake/sanitizers-cmake/tests/asan_test.cpp":"a25de95282aaee22d977d0b474468b946c1422b80b15424c04266dba038eba2e","libcubeb/cmake/sanitizers-cmake/tests/shortest.ext.test.cpp":"a25de95282aaee22d977d0b474468b946c1422b80b15424c04266dba038eba2e","libcubeb/cmake/toolchain-cross-mingw.cmake":"1c26749465364061ddf37aaa00f363eaf057c4b6a70181086e13b0a4d09bd376","libcubeb/cubeb.supp":"19f33e59f8dc91a327c923e44c2c3f9af0a043ce1d6a8cac275ba094b4bfe0da","libcubeb/docs/Doxyfile.in":"0815f19789cedd310652a133bab260c27b57e95f7a65458df2dfca38ea4f1041","libcubeb/googletest/CHANGES":"72c8a289bfe4dd9160074a3a2238c8067a5bc7ca49fd87f70a134c3f373932a4","libcubeb/googletest/CMakeLists.txt":"cdf938ce79ea066866dc614de3925bfaa48d9e19e04049db2ec8c5443abaaa9b","libcubeb/googletest/CONTRIBUTORS":"4d911cd5e6d71f3f4bbcb2788b2f916df4b0ce1e088752a159457a1d936ae0ce","libcubeb/googletest/COPYING":"9702de7e4117a8e2b20dafab11ffda58c198aede066406496bef670d40a22138","libcubeb/googletest/Makefile.am":"a795e5a18e82ba06fd97509d92d773b7fafd0dd7086db8a1211fbd151b503bac","libcubeb/googletest/README":"484b19654362942fac9734c8fab0ed3d99249b81c69027bdb7de46054abada6b","libcubeb/googletest/cmake/internal_utils.cmake":"6f4670a5825cf8ae0415be9dd43d82a7f30316d75cab20a4c60afb6d9db2a01d","libcubeb/googletest/codegear/gtest.cbproj":"9fa07a66b8c01773256e508187775407c465ed9055651e93d390426d1888721a","libcubeb/googletest/codegear/gtest.groupproj":"76c001cb2ee0070e26d1570fb6db5250f2585179c707496c5ef6d12e582cf205","libcubeb/googletest/codegear/gtest_all.cc":"c8750dc2b7b3612edb60e8d23fc2f60ae264451916c4b15f81cbf60ea30eb75d","libcubeb/googletest/codegear/gtest_link.cc":"e5e47c086f932471e0ca748a62b3b1597e5e731f4d34fb8cb8b2ca2db7ba3ed0","libcubeb/googletest/codegear/gtest_main.cbproj":"056448ba7f41fae3f704b1001922d9f6e419cf8cbcf3a55bf0ecc59ece1fa9a1","libcubeb/googletest/codegear/gtest_unittest.cbproj":"2c48be90b0dbc3224a8bd6c4dc21f78dd1b08c81685e6bd4952bb6df6ee38701","libcubeb/googletest/configure.ac":"fadebffdaeaccebb60fbe4a501c1138c296e01348a5da45fabf5e4233248baa8","libcubeb/googletest/include/gtest/gtest-death-test.h":"fdd087f700cd04a3ce4bdd36f35769de52a44bfc0c5bae2dc9681d4cbcd3c44a","libcubeb/googletest/include/gtest/gtest-message.h":"eaf44df1284d94333507c47091c84eaaf43814e6a02a1b1c0061ca7b363e74d6","libcubeb/googletest/include/gtest/gtest-param-test.h":"f226f0a24c04cddbceaaa45d8a5e575ce18c3392349f9b8ba73317e37e62368d","libcubeb/googletest/include/gtest/gtest-param-test.h.pump":"17c65fd5cc5218279044a61f3873c9c952b0924a7ba5147d4999d400b122207f","libcubeb/googletest/include/gtest/gtest-printers.h":"7046f611398d63ee0f1c37bdb4fd08d9931979b2fedf13b781e6d85d4b3b5d60","libcubeb/googletest/include/gtest/gtest-spi.h":"560407dd45e8e57fa6927504c9e4a4cfdecf30f8cada975c1ffddce765e6a88a","libcubeb/googletest/include/gtest/gtest-test-part.h":"c4d6d840284728740c284646075e8ffc85b63b9f74f3ed488b18ef3c2c2b9005","libcubeb/googletest/include/gtest/gtest-typed-test.h":"1ec858bbb9ed8a8bb553232df016437c080b2670f00453b4de297c286eb78c21","libcubeb/googletest/include/gtest/gtest.h":"47433ca72a43bda7a380c34fe6d4ff451797c687e9bbd74d1f366bcdfa0cb013","libcubeb/googletest/include/gtest/gtest_pred_impl.h":"f03a3f77e3c231889c0ace6f63b2c4e410e4a9330287ea09443b23b9a3cf9092","libcubeb/googletest/include/gtest/gtest_prod.h":"4a99a3d986a45b4d6d9b3af54809f015c54aa98274793a4ae173f5010d0ad33c","libcubeb/googletest/include/gtest/internal/gtest-death-test-internal.h":"0b3abead866363f3e6b4201acc8d2763072e033826b22ae5ebffd790e1415235","libcubeb/googletest/include/gtest/internal/gtest-filepath.h":"638d2bb6c06a894513b03311a8e931ac835fc00afc4bd21fab3afc05732c23a0","libcubeb/googletest/include/gtest/internal/gtest-internal.h":"12c2c83df0a9dc5b46697ccd8271dfa34ee5f3d1972dcb56585bc1459d9583c9","libcubeb/googletest/include/gtest/internal/gtest-linked_ptr.h":"9bd319548dd073630dfd349c06a440c6a582feec47d4ff14f348ec32f8b4c1f3","libcubeb/googletest/include/gtest/internal/gtest-param-util-generated.h":"10db93fa7e98820192bae6f560664469dd33b265036fca64253c89b6801f96cb","libcubeb/googletest/include/gtest/internal/gtest-param-util-generated.h.pump":"abb72365d94d2811b34c195dc520fbf41c7dcb42aae5a1cfa0502cf619b21e70","libcubeb/googletest/include/gtest/internal/gtest-param-util.h":"7f9311f033ef6916217d87cef53b1db6c4e8733be930e4b48fe7e11d21b33da0","libcubeb/googletest/include/gtest/internal/gtest-port.h":"612932c2930a7cf2c3514d89a8d6b51a2c0030d251309b71765ed1c9954e20c5","libcubeb/googletest/include/gtest/internal/gtest-string.h":"a46aa36165c400d1e926f942be03fe04cd7ccb1e59f7a2a03b919c4eea05b997","libcubeb/googletest/include/gtest/internal/gtest-tuple.h":"43e7e3c92f8e4258cf3927a9204b214d4d03e6c796f88f3ad4e66b1ac20aa938","libcubeb/googletest/include/gtest/internal/gtest-tuple.h.pump":"16fa027ed3c5940699e0ac906815e66620993bcf75b0acaf826d4f09348d4b83","libcubeb/googletest/include/gtest/internal/gtest-type-util.h":"6d177af46a9b1e14b969972a8b886667f95e69037aba411433a44fb9b92e7037","libcubeb/googletest/include/gtest/internal/gtest-type-util.h.pump":"22092f44127af91651f57ce222e20914d5d32ae02f1c0964f6d5d7bc019af339","libcubeb/googletest/m4/acx_pthread.m4":"3326e3746b6b351d1671fe31f798269cda8de92c365b8a8305404ec0fa6c6b32","libcubeb/googletest/m4/gtest.m4":"d3c37ebd1aa792c967d4357755cc670bc6deb30091d9e6db498871d90a30ea4c","libcubeb/googletest/make/Makefile":"9b86e2a112dd55c6bf6a2b39e6f4078faf60cfecb8282ebf9b025167ed233420","libcubeb/googletest/msvc/gtest-md.sln":"0beab679b42cf0c431eaf4fe143bbf3b01fc064e20c74d9e33e7e437a70487d4","libcubeb/googletest/msvc/gtest-md.vcproj":"52e873e964daf9d5409b4e9bb471ddf2827be04985cd96c40620f9275d17a256","libcubeb/googletest/msvc/gtest.sln":"be21c2340650ec2259a2fbaeb8608ae6d3e982a0626a0f91128a771dc88e6bea","libcubeb/googletest/msvc/gtest.vcproj":"0064616c7d88a284c1b7c05baab038f239134ea9c6c563628f286f9600b3f921","libcubeb/googletest/msvc/gtest_main-md.vcproj":"f83a294a92b616bf34ccae6743ff916297bdba61d6125a9637a813d467a30372","libcubeb/googletest/msvc/gtest_main.vcproj":"9f03270a00896eab0c7015c6fb1a73818d024e462d3944ba1d3ceb313a051649","libcubeb/googletest/msvc/gtest_prod_test-md.vcproj":"7caa108733e2d5f140da004d2133e04a9a105811909c0e2d4ec06e2971983592","libcubeb/googletest/msvc/gtest_prod_test.vcproj":"cf5bfb7f3de9a59a0eba5535067845d12c33c3fd8fecc3d03aa702665db29578","libcubeb/googletest/msvc/gtest_unittest-md.vcproj":"e7949b21cf0418f2a7afe8aa94616e2c40e3ba0801c2f0826f3a3a3d2e6f48b0","libcubeb/googletest/msvc/gtest_unittest.vcproj":"5b097d596fbbc1c4090fd518008a0961b29661194e1c02d8a2d3daaa557e626f","libcubeb/googletest/samples/prime_tables.h":"2903df1d1e6643a5f624fe3ea3f931c3410eb1858ac347c5df278273c6c91ca4","libcubeb/googletest/samples/sample1.cc":"dc106c5940d87bb4bbef3d77815eab642ee173a3340b2b9c532b5c711c4c2d0e","libcubeb/googletest/samples/sample1.h":"7a7bf9a0fbd2401e8b2cb554bfcb9bd0ed228212f3b970675c1b1d38d4e188bb","libcubeb/googletest/samples/sample10_unittest.cc":"ccebb6393a5a8468399f7e511219b667a2233f82312ce59834a4bb0997d8700e","libcubeb/googletest/samples/sample1_unittest.cc":"904be0d4a095e74393515195392bd10e1e916bb2ca61f3f94b1bd6aebea29cb6","libcubeb/googletest/samples/sample2.cc":"f14b8a1e69d52eef1a70053fb256818c7eca64e8eda08de43cf46e896e57fcc2","libcubeb/googletest/samples/sample2.h":"df956ba520dafca068dbc1e28f36567db3cba36293e06762318af8cda6a12bd4","libcubeb/googletest/samples/sample2_unittest.cc":"abe7e0b253d328cb82ae67623fbe3c89eb94699102510c64a0b568eaca101e05","libcubeb/googletest/samples/sample3-inl.h":"3fe482bbd4f725f5820f5d6beab4d0d4a524be8addf4b344a9a470ec5aabc451","libcubeb/googletest/samples/sample3_unittest.cc":"252c06b4531dc35213ebdd7311700b9b4057bc1bdeeba0cd767b2bc86c456639","libcubeb/googletest/samples/sample4.cc":"b4260f5fa35d78ac114a9abb59fce12403faf0273df41f57e83c341ae7979222","libcubeb/googletest/samples/sample4.h":"604905cae7e5587805c3b884a36eda7a2bebdfedb53b24b0fd9a220eec0ef1a9","libcubeb/googletest/samples/sample4_unittest.cc":"6cfb4821d8cb1c77fbb5af4f8aec569948762d8ea314827e3ead967b5b6a223e","libcubeb/googletest/samples/sample5_unittest.cc":"73646d9038873a68bb2e56b12495d7f7b65b5c23901109701da446af454ba2ec","libcubeb/googletest/samples/sample6_unittest.cc":"833fee399954f908cf0f3b789832e505329787f4cf73607a7b31ca0f62f368d7","libcubeb/googletest/samples/sample7_unittest.cc":"8013ee68d61c181e4e936cdae3a9a635646274f8512033ef11bff7214e03e4a6","libcubeb/googletest/samples/sample8_unittest.cc":"7b7510fadf4955d2f934d23d652dbd35add832e50bdfcc98421fb9be4588d808","libcubeb/googletest/samples/sample9_unittest.cc":"8b827040dea37b460cbcaea0b255b98974a9840f6ef7bd82aaa7d4ad2c724335","libcubeb/googletest/scripts/fuse_gtest_files.py":"adecf64c6bab65b31740c321e568cf174f753d5617745aa5762d842339d68b53","libcubeb/googletest/scripts/gen_gtest_pred_impl.py":"78fb7e20a014c251d723186eb58040e4eb32405b73c9288d787ea0a0e4ff5183","libcubeb/googletest/scripts/gtest-config.in":"9a43978eeee88e188845d737c17f4d024d4e74feae09da7997e8fbe4ea6cc176","libcubeb/googletest/scripts/pump.py":"3856a3d7be37f78e0f214ee7d4f29d05f1ca14218b67539d67c9a16e992f670c","libcubeb/googletest/scripts/test/Makefile":"3576b257594a2d8e843b9e4de8c83353d837833bb86431fb1b4198022b1bcddc","libcubeb/googletest/scripts/upload.py":"f75d0712e3b13bebd8daa0a15e4eb32c9e3034a933f4fcccf65b1e999a7ae066","libcubeb/googletest/scripts/upload_gtest.py":"6e76fc0a7a3831c01cfffd18c220d44438073a66338d91ca61fc84b924021e61","libcubeb/googletest/src/gtest-all.cc":"568ac119f5e6418f1fbcfbdf185d724657d7f3539b47822da229ac5d015626b2","libcubeb/googletest/src/gtest-death-test.cc":"eec1b3c8252670c76acbbaf63483946897ce625139b53a566406b6313f023896","libcubeb/googletest/src/gtest-filepath.cc":"31b7fcda5d11346f8a487597c6a70ff057f1192e0cb11f27eb7841a9f3aa8b86","libcubeb/googletest/src/gtest-internal-inl.h":"c9d428a6b5990ace091e40c4ce8b7bf6c50c186a8314b1c4a4cdc988ca0ac1a4","libcubeb/googletest/src/gtest-port.cc":"95bcf473622d1b901c734e5c2aeb8efb058555ec924212a61bb04f049bb5a069","libcubeb/googletest/src/gtest-printers.cc":"6f191a7fc7f5a0a967fd11964057f2e2d2eaf2f37ccece16bd816531f52b3154","libcubeb/googletest/src/gtest-test-part.cc":"e489868b4cdc66f4fc33bc2326ac86bc1acc5808ab58bbb288c9dcfc330faddc","libcubeb/googletest/src/gtest-typed-test.cc":"ca9e819df728c25a6a1fc072806c22f3494e1dffe4bd0d48284f38dbdd3a0dd5","libcubeb/googletest/src/gtest.cc":"5cf9a3e897892c9f0e5c887f91d3c8c8c5665bd7348560441fc0b946c254873c","libcubeb/googletest/src/gtest_main.cc":"22fa1f77542b882d1798d7f696045c5895942a626e26200a175fa4382e1fa5b5","libcubeb/googletest/test/gtest-death-test_ex_test.cc":"613ccf50a3ff8f84c975a13e86ea01ea4e36933072388a3738b4acf9ed3ed7cf","libcubeb/googletest/test/gtest-death-test_test.cc":"df8384a847bdf889233c3d45d171f784991def7a9b6a08442138569fbae32b9d","libcubeb/googletest/test/gtest-filepath_test.cc":"49760f91723845b113bb60bb9b1a1426ed1da1f4ebfef2462128980ea5692cc9","libcubeb/googletest/test/gtest-linked_ptr_test.cc":"1b9cb4ff67475900db9de34ae9749b94193048a1f7a741091ba5a2dd7fc7a79b","libcubeb/googletest/test/gtest-listener_test.cc":"acf78f2c9a730525ea5adc93e9196a42de8fbfe488db1dfd02656bdbd477b2c0","libcubeb/googletest/test/gtest-message_test.cc":"b1fc68f8b75ce25fbd79b3f7d3c9c793381ef07b3203e1a2d9b610cb597542be","libcubeb/googletest/test/gtest-options_test.cc":"74e3ae0c310edb3139b0032266219d3ce7f386ded6feafa57fef03f4493ed7fa","libcubeb/googletest/test/gtest-param-test2_test.cc":"a0f1efbcab3f7e49df639383157626931f64756f7e738be081760f93f7308332","libcubeb/googletest/test/gtest-param-test_test.cc":"ef8bd344e959053f562b0c9e0d15e2fb6c1e534772a67aaf3f90bd6bad0bf99f","libcubeb/googletest/test/gtest-param-test_test.h":"9d7f47b79d54df7cc050aa6038b0464aa684dfca669a847bf70ea16e4a000628","libcubeb/googletest/test/gtest-port_test.cc":"1600f78ef0860a0f5b5525e5e5041ff32a216cc6ae948b1ea61fe04ec603f67d","libcubeb/googletest/test/gtest-printers_test.cc":"7898e4b4163ee0821fed248e1c75d9f4a0a511a2b4bbfad1ef2f4a11a099f6e7","libcubeb/googletest/test/gtest-test-part_test.cc":"62c8906bb0d12ea84d60217b3773cd8e1768db4aab934880db2316df7026cab8","libcubeb/googletest/test/gtest-tuple_test.cc":"2850dc1f73a3f8020d8a4d80688a28d9b736eae6d677222c3f871d8d33b25501","libcubeb/googletest/test/gtest-typed-test2_test.cc":"c52b65e7181610d6e577631cd50177399884913ff28d08aedfedc92f05185044","libcubeb/googletest/test/gtest-typed-test_test.cc":"c7daff5211028da79b3ca0473dca18ada9197f38e710f72d0493ad3332ce3ec9","libcubeb/googletest/test/gtest-typed-test_test.h":"3145698534d8869beb624c9c8ed114f75bead046b2eeb92ada5a724993ee7786","libcubeb/googletest/test/gtest-unittest-api_test.cc":"e3f54c28ef2849e8b12af666ed46aace50c3e047845072ee6f974ce4528bd297","libcubeb/googletest/test/gtest_all_test.cc":"db0c3c42b385570b1d517e3ee927671b8fad4e206247fca738ec477222ac3d97","libcubeb/googletest/test/gtest_break_on_failure_unittest.py":"11c91bc1c68cfdb913e2affb01261b55fb3b0c18773a45875e9c25cb330a4dcd","libcubeb/googletest/test/gtest_break_on_failure_unittest_.cc":"1da12e4bdda2a0bc7b59d4638fe34b2d3798134224fd9237eeebdd09c3326011","libcubeb/googletest/test/gtest_catch_exceptions_test.py":"305cef45c6dc034bdf72fd91aba1e89e1c6b5d222c3d6baffff5acdfd9b3873e","libcubeb/googletest/test/gtest_catch_exceptions_test_.cc":"b297a4f4d5bc0285ea9eb8869741631658305e49d4513bca904842aacb82128b","libcubeb/googletest/test/gtest_color_test.py":"c4cb006682a40f2d88759a4bcabf0d4be623720b135c71447f1788d17ea23d0f","libcubeb/googletest/test/gtest_color_test_.cc":"f263ba349afe58a558bf0fee98a98bb9207a648e7cd4f908a87799bd13d001ea","libcubeb/googletest/test/gtest_env_var_test.py":"79819598cd1e366eaa8f2a4fee2d638b6ef0686e490402fae792ccce58d876c0","libcubeb/googletest/test/gtest_env_var_test_.cc":"0eee5dfbb2a2598f4e76626346b921928ec1e052e38f254cc97c60d05611ab46","libcubeb/googletest/test/gtest_environment_test.cc":"a52a21ea29c2203b03fa93922733546d171f98d3b2fcd42972269e98fd124715","libcubeb/googletest/test/gtest_filter_unittest.py":"edc7d278803bba41626eacd050d91d7247f1c5999f9dceb99a8877e238bc73d6","libcubeb/googletest/test/gtest_filter_unittest_.cc":"996ac528ad75c293d8201ce28cf6acccee266286bd369b4cf43f05b8d67a4559","libcubeb/googletest/test/gtest_help_test.py":"b43ab690c08e4bffd84a47b361167496298697f9511bdf4a745bf305b5cfbdfc","libcubeb/googletest/test/gtest_help_test_.cc":"ff4b121098f0fe7cb4abf11fdd31f2fe7a477286ec9175482138bc038d61c807","libcubeb/googletest/test/gtest_list_tests_unittest.py":"7caebc175b44b3c727fc50420ada1a6a9500f3e4ce9e2839f69205437aa85e7a","libcubeb/googletest/test/gtest_list_tests_unittest_.cc":"d82d8b72914897232c2ff9fd091a7b0add68b7cf75f3f210d3a487ebeea84cfe","libcubeb/googletest/test/gtest_main_unittest.cc":"0f66f318809c88f0fbe034a340a75331720c4e33be5378022baffaf588ef1202","libcubeb/googletest/test/gtest_no_test_unittest.cc":"7cf487e07c3d27376c2cb8af33d02239b7966623875d37b7aa0259e927a9c2f6","libcubeb/googletest/test/gtest_output_test.py":"cf0dc1979572d94450a5e611b44f3fdb88d9cd980d669a723f0ed63057b5e2c4","libcubeb/googletest/test/gtest_output_test_.cc":"f69569374c2b3d06aa04a38ebc4f92ddc303e6af503f8b533cd8e6bf9f104899","libcubeb/googletest/test/gtest_output_test_golden_lin.txt":"4f3e49c10a524a99437cdcb5294e3335a7f3c07ea8462e65730f703a5fe4fec3","libcubeb/googletest/test/gtest_pred_impl_unittest.cc":"e406eccf75b6b58746a95d1c7ea7bc8e80ff974e438ef7c83074a46d4e62db9a","libcubeb/googletest/test/gtest_prod_test.cc":"b42ca1a6d0a1e43bc576b4ff7776c6d2c37234f6dc2a76f2735f261b4a47a526","libcubeb/googletest/test/gtest_repeat_test.cc":"e10abbb71595920aa3bb415029eed74106335fc9ea3d58c417ccfc7cba6a4cdb","libcubeb/googletest/test/gtest_shuffle_test.py":"12dd94eb5f30260ba37059fa74658bda57dffa821f3ba6a2a8b52ff14b1ad029","libcubeb/googletest/test/gtest_shuffle_test_.cc":"af1b2b01ae275f1a9fee7e7940c0f88f39ded063008994d585aad87e3ffadb39","libcubeb/googletest/test/gtest_sole_header_test.cc":"538414c27a593ab8dc34c37b5c877eb3a022d75d1b481ef14ceca00914929754","libcubeb/googletest/test/gtest_stress_test.cc":"0b02fc12f87944226915a999bdcc8a3eaafb34a1ea5bb0df128774abf8667f09","libcubeb/googletest/test/gtest_test_utils.py":"d4a76930aee6658ad8734981ca0c4ea14f34dbe8fdd31d5afe41f6d98f9779ee","libcubeb/googletest/test/gtest_throw_on_failure_ex_test.cc":"11ae790028da20bc7b7af1572eff3cfe8499be43ab64c110e18e1892612a183f","libcubeb/googletest/test/gtest_throw_on_failure_test.py":"ebe18ca0b07f90c53b9b3f9a54ed02df94facf8995cfa90dd41c6f5474537c13","libcubeb/googletest/test/gtest_throw_on_failure_test_.cc":"f8cbf75d8bf9e9ae068a17ff968434c3aec7b7f1137c994d8f14af1a84361aa9","libcubeb/googletest/test/gtest_uninitialized_test.py":"da8e6ce34930753e36fc1dfa2c3e20e48d02bda2a27d3d03a07364312c5f3bd9","libcubeb/googletest/test/gtest_uninitialized_test_.cc":"0b6a9d4983480f87352ca4da946089264b401f7a4a3b1282253fd6cc861bf483","libcubeb/googletest/test/gtest_unittest.cc":"c0c7d1f691ce1e10c3d1647ed5f7a66510725808ad58bb6da4bc03a7a08fb2fc","libcubeb/googletest/test/gtest_xml_outfile1_test_.cc":"29341d777a9c9d25f360d13ed966b30f0cbef1fc88aefe2f01bb88b82cf1ed93","libcubeb/googletest/test/gtest_xml_outfile2_test_.cc":"da7ab3cf0e9b2a293eceed7c5691233d6b61afb557e3c1176dfb75390f85be46","libcubeb/googletest/test/gtest_xml_outfiles_test.py":"b07927b43f44afbfd61761c2cc69f1b68c4fbdeddb992db03ff0c73052518cd4","libcubeb/googletest/test/gtest_xml_output_unittest.py":"b5ff0c0207238d01cada961b8f4656f2ec30a3e1e5bf9d22efdf1745af423031","libcubeb/googletest/test/gtest_xml_output_unittest_.cc":"ad0b9ebe63a146e386df3c5c51916869f6d4647b9832ceacc912fb1272d15f82","libcubeb/googletest/test/gtest_xml_test_utils.py":"ad89a39a6cd5b08e87082341f3e7800dbf1150ea0f1386e0b8cd374aa6832f00","libcubeb/googletest/test/production.cc":"56fef77c3a8e62073ec11653d740a8e534008a0d57925ab0877b843f4fdd6be8","libcubeb/googletest/test/production.h":"a36d10545d12ead5e93a3b0fdca6ff73405f29091cfe38164415e9038888ba8d","libcubeb/googletest/xcode/Config/DebugProject.xcconfig":"fb42302df29bd8e8b5237194c0c04941f0e578527037930d88469baeb7a7f62b","libcubeb/googletest/xcode/Config/FrameworkTarget.xcconfig":"9935ddabe221f074d2f3b969a137d12b0dc0f845a460f58b63232987cb0f37ff","libcubeb/googletest/xcode/Config/General.xcconfig":"0fb768924daba1048f8db28b3a1fbf915b6f788d49d9d37e85979aa4ee92e02d","libcubeb/googletest/xcode/Config/ReleaseProject.xcconfig":"a4878ddd1ed78fb411906623cb51bc0ab4aea1cc3feb5379d2ae2862d8bf3bf5","libcubeb/googletest/xcode/Config/StaticLibraryTarget.xcconfig":"5886291788b3e9d5aadcb979ff055fd26a2413be81016e7afffb813b627d177c","libcubeb/googletest/xcode/Config/TestTarget.xcconfig":"f074e6c2516a6063b253ec6b842d74f5c2abefc7bcf8d8da54097a7bfe016480","libcubeb/googletest/xcode/Resources/Info.plist":"5b7f78a6d5810ce5490649793175c8982d41e6b49af06bc0705bc061567cc9aa","libcubeb/googletest/xcode/Samples/FrameworkSample/Info.plist":"1c13d83e5eed45689d7fe4bf4681030366474bc40608e39e1623c1350513a0cd","libcubeb/googletest/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj":"1cf0e1b1abf84414372faf9c8bf634e01fe5750bb3ca769b1eb25fc530b21358","libcubeb/googletest/xcode/Samples/FrameworkSample/runtests.sh":"a587e5b00a8353dee0aca5a4c59b28301ccf7648dee8c79b62a9223f9fc3c8cf","libcubeb/googletest/xcode/Samples/FrameworkSample/widget.cc":"562a2bb615e93186012823c9b41761769638a11e38b54498ad5f699038c8fd32","libcubeb/googletest/xcode/Samples/FrameworkSample/widget.h":"0c7915e45cf7cb8d67db24e49cd0b277f23f967578f917f8e859a6adc4b156f9","libcubeb/googletest/xcode/Samples/FrameworkSample/widget_test.cc":"6a1a49d64912d9829ef3d991faf5a3f0e1e081126a1d8d387cdfa84fab70dc77","libcubeb/googletest/xcode/Scripts/runtests.sh":"1a0672a4151b16f3c797478ba26c534e82b2faa603f90b9aa14e785805f7683a","libcubeb/googletest/xcode/Scripts/versiongenerate.py":"4b9d5c0f4e1b556084109311d156bee6d781968dc5b1dfdc8702364508f1dd43","libcubeb/googletest/xcode/gtest.xcodeproj/project.pbxproj":"a1224decff058bfed01b8eefaee13cab0129492615548c6d0d878003a154f7ff","libcubeb/include/cubeb/cubeb.h":"7fde26ac5d7b1754369abbe66b4bed148e0ce5af17304cb869a85fe427e558f2","libcubeb/scan-build-install.sh":"1ecf22aca367a4d02f810c4cb78db8636e08a12787e94e30c441ce439cf4a265","libcubeb/src/android/audiotrack_definitions.h":"0d5ec772f9ebf61333bc16e61a081a7e3b4cc02342ec4f8f417e220d032fbbc6","libcubeb/src/android/cubeb-output-latency.h":"000fb7bec38105f54b9d40fc436440c637d63390b219775d335216d29d767226","libcubeb/src/android/cubeb_media_library.h":"f67965fb2ea38f0023eb4c76024341ba9563ac1a135507b6f12a9aabd85e30a9","libcubeb/src/android/sles_definitions.h":"66d10b157e463ee106236736b0338d1ec512d66d577ecafda56427bf14658443","libcubeb/src/cubeb-internal.h":"ef7e7e19c40f743c814a39b8a47b9f03df054894018ad88b49129ffad2564bfa","libcubeb/src/cubeb-jni-instances.h":"8195554372bf60dea569873c9e5fb1106a2cf5dedc66a13d2bc967da0ff48a12","libcubeb/src/cubeb-jni.cpp":"81f001720c41c69b5927e32bd19b9e8e7176d7c33d63c2a58bd0d695dace4fd2","libcubeb/src/cubeb-jni.h":"73f810a32087a6062fd49ba89542655a7e19cecac6f40f8411e1d77ce42a45d1","libcubeb/src/cubeb-sles.h":"dc84a01ba4de9db1ff108609930b36ba442020ccc3e3d6f16528f429426c430c","libcubeb/src/cubeb-speex-resampler.h":"dbf543eee4cc6e40ba3531a39d327e2cec884c19e26c570aa7eae0647e5f7420","libcubeb/src/cubeb.c":"537d418a17c85c855dfd559e07d2593b09489ed51fd3e8b2e08586c1c9a54288","libcubeb/src/cubeb_alsa.c":"6c833e379eea5d64a65a209f8e60c2aa2d6e038ea855554cd3f2664c463abbcd","libcubeb/src/cubeb_array_queue.h":"5264ae02799c540ff73e8eb8efa55986772b22562a025ae227c2603b6b8d1036","libcubeb/src/cubeb_assert.h":"ab8ed4fe7070a3aed9419c5f9695fce2318c4dafd91213ae61cac476e64adaa7","libcubeb/src/cubeb_audiotrack.c":"fe66d36dfecbfaad164ee8c871b39fd6e708a2f8f1f8524a5c0148ab86bab467","libcubeb/src/cubeb_audiounit.cpp":"9b869e260c32f0fad7b1f05803efcaa0a9afabf6cddf118e0be678424bc1be48","libcubeb/src/cubeb_jack.cpp":"129c011feb01e8c6d573862218c31a8bf90522539a28a5ece8bcf87867be9daf","libcubeb/src/cubeb_kai.c":"a71e1de94211ff0e5667a218d71588f1e74102ccf0140b80925c277949871095","libcubeb/src/cubeb_log.cpp":"74bdc0d92a31d6b4ce3c376c6d310db583b869d673e40e6bd0ea795a1e2f937a","libcubeb/src/cubeb_log.h":"ee05fd22ed9820bed79247b8603cdc64f67bcb145be47e78bf0a0e99fb6c0806","libcubeb/src/cubeb_mixer.cpp":"061427a06516792ead3936a643224c3d275913410f67765cc24e1b8699e8d99d","libcubeb/src/cubeb_mixer.h":"e94205c1b98859e41eeab2cad53f635f34f57a2ae95aa23a36461a2619abf81b","libcubeb/src/cubeb_opensl.c":"973389c53f0d8524ed2d2a64e66c942fbe5365b75eaa65ccd4b20cc12e66f96f","libcubeb/src/cubeb_osx_run_loop.cpp":"13c029f7ea04808597b8841b13f248c4476fb7425762f01a59bc6c944cab3a78","libcubeb/src/cubeb_osx_run_loop.h":"ffe80df60b8ea3d0341715b72cc60aae2e0df45141887c01117df543260a0ef8","libcubeb/src/cubeb_panner.cpp":"405a115ff0eb5f00dbab6bc8f2999b02ee4ea4792a87bad7ebd7218ee7980438","libcubeb/src/cubeb_panner.h":"5679df1b9d138c91f6ea642d51e6230cdf3163bdd65db156ad45906916cb74b0","libcubeb/src/cubeb_pulse.c":"281d8115f0e6759ecc5a323c8d61f70eb27e339539946253a773924c2fd9c491","libcubeb/src/cubeb_resampler.cpp":"f58deac4d17f004e8b31773335bb0cafbde08494cbda8453fa39a36617e47337","libcubeb/src/cubeb_resampler.h":"ad9800a40c0272fb2a451c02367cc5a516a3067d4acf963d35eb31be367f9224","libcubeb/src/cubeb_resampler_internal.h":"4b4eb6aee343b9c1f73cf17b201329d3714ba44b06ecb1cebf950fdf93a9dfe6","libcubeb/src/cubeb_ring_array.h":"db8dec7a6d778a424045e5ac61c2bc3a3cec8c4fe8e4780f383db4b6f1b2438c","libcubeb/src/cubeb_ringbuffer.h":"2296255ca7835a3ace2fe1852054f43428b677f432b4174bd832ad0224a409eb","libcubeb/src/cubeb_sndio.c":"6613d8555b4faf1f047d706ae37473effaa645d9846458eac24ae0973432ce61","libcubeb/src/cubeb_strings.c":"60f2b8c03a5a01925f9777eec0ab84b0e704b40c03e0d6b9c0e7a16246c81fde","libcubeb/src/cubeb_strings.h":"00e5dc97cf16e28cfb53aaae50ac0e3c0ae8a82aad0720ab6842ce5d9785c39f","libcubeb/src/cubeb_sun.c":"b0269c4b9fccaa44a11ccee9afa074659710591aa99e75e0d2e33724f20414c6","libcubeb/src/cubeb_utils.cpp":"5bd7de8bbf7bbdc3a275525edd92bad590fb90fb4d35e77017fdd5d25a5769e6","libcubeb/src/cubeb_utils.h":"27baa42747771bf9232741382b83722f5c731e5dcd4dc2e9b595aca91c5647a5","libcubeb/src/cubeb_utils_unix.h":"2a48bd2aefa1b4e4e4968121512bcaaa6be3bca6597ea390b8203c338f5c49b5","libcubeb/src/cubeb_utils_win.h":"74658b6266a8a223c681b0fd06fcc9c891c7b0b95377635c6f1763b240c2ab27","libcubeb/src/cubeb_wasapi.cpp":"ab8cd5c8aa5dbd0f9180697d17df4bb00c0c61319d464154d37a368971163ef9","libcubeb/src/cubeb_winmm.c":"4f3d2b1e51b45f75e524a74d5b0adecc47db39a1204cf2bfa46741169f73d121","libcubeb/src/speex/arch.h":"2300bce68c588270cdc684dc7f01377e5e251529f4545d93771e111c56d51b0f","libcubeb/src/speex/fixed_generic.h":"306ee7453677fa6067f16c79d358c6c90a9d3d008850b493cdaa59c07e6375c1","libcubeb/src/speex/resample.c":"9c3a1c64ecf3750af82c980d01ea73d3682f73c332a580465d1e787e5c54cd00","libcubeb/src/speex/resample_neon.h":"7d3fd7af9a1ddde22518b9c7b4419073b72b2dfa5be4c3bc8796992bc87b3da0","libcubeb/src/speex/resample_sse.h":"5a196d8e2d8ab5c956f5252f09f5ddc55aee1f99b1341af3fa54a1f4c2157924","libcubeb/src/speex/speex_config_types.h":"24e3ffbf29e5519611a48e5acb959645b01d166dcb4369380d5f776c3f53d4cd","libcubeb/src/speex/speex_resampler.h":"7e439ec0dd30c32216b3ced17135f8992e5aaf53389d3f5996a7d900c453e65f","libcubeb/src/speex/stack_alloc.h":"e8a2fc0874942d2c7177475fcc141fdd0c0156200b8a4e7656d4a20313e2e569","libcubeb/test/README.md":"1c11b038f87daf10ea78abc17bdbdd157940c241df548c24d5872d142a98c1af","libcubeb/test/common.h":"968144634f3ce627d7f6cb91d48ddc6f1fa89f481ae63f80a7cbe743989e449c","libcubeb/test/test_audio.cpp":"95337fd7f55c91af5ab0988a727566ecb04314979094834624d5c10cb206e0b1","libcubeb/test/test_callback_ret.cpp":"f2d190ec14b2da927bb4cd759f775cd3b7f38df3cd2984862b346f7c37eb9ca8","libcubeb/test/test_deadlock.cpp":"0e28e59f360e27241536879d9e02e4e05291db252f66fd601577aaf723e06543","libcubeb/test/test_device_changed_callback.cpp":"c30bcd2ec4348f56c520952cef18a47c430f121cad59d64d648498c14e79f080","libcubeb/test/test_devices.cpp":"8c61e4319af2af5a59103fccd216c666424d42b859b8719166513e26eebd39c3","libcubeb/test/test_duplex.cpp":"fa9944a3d7975b21ad0b61690f2ab40c4ed16a4c3f2758d7b6ad0df60cbb0768","libcubeb/test/test_latency.cpp":"dc5af071df0ff0c4b2f6cf7b37438ac8ed9f18cc0fafffb2c685b1e82201c9f5","libcubeb/test/test_loopback.cpp":"f67c2828e2e238f07a0d1371d42ae916b9d7decfc4233fcf4d632346ef98871d","libcubeb/test/test_overload_callback.cpp":"f3ffa014a0e6f7871a023b46733f93d992ddc9b41e0974cc22a365979b6d989e","libcubeb/test/test_record.cpp":"89a884872b780005b2fb29d106b6f33ddd76b2fcae381395e17d3413153b3b89","libcubeb/test/test_resampler.cpp":"ca4bc0493ce0c3a5f02f389ac6e37bc2cdb9a752faad2b6fbc5af0a2223ef645","libcubeb/test/test_ring_array.cpp":"27836d716616abf8b020a710659c10ac5e1d4b64149d22cb89bd7a7a5a5669d1","libcubeb/test/test_ring_buffer.cpp":"4ca684e38f1d34bb1f625ce2a2a730e5b24e09d1107f108e8b80731e55315861","libcubeb/test/test_sanity.cpp":"509cfaa6ad932e47861c00236ae27b59056547355bde78707dbe34a17a5005a6","libcubeb/test/test_tone.cpp":"02de19023d203e2d538c4f8ae23574153a4df6ada1d06fb83af2d51603b61669","libcubeb/test/test_utils.cpp":"e8d7a02a9096dbc0fd15d71f9849415d52958d2ed82cbc7b8507d3228e08d382","libcubeb/tools/cubeb-test.cpp":"10adb630fc1d0ab965e689c571ea2bdbef50006fd32521e224e16309737e2537","src/callbacks.rs":"b4b4eb3f370475488d7c77b338b0bceee94ef59ede8ff41fa797a3d35ea98b5d","src/channel.rs":"555bc8d5257496cf6e5b4c786df84755327d88a9dc07202746e35f3b7b7e4e0b","src/context.rs":"96bf3442b1dd40262d3088dbb6c473f5451fd91320cef93c522b40f284599803","src/device.rs":"5b65e1c1fdd53fa5208f20bfb809475cbb3c434e02db7d0e4771d13c86f8e369","src/error.rs":"406e3b843ed2d263fe677c4b34fb96a6d780a68bcb56a6f85f041d20d70227bd","src/format.rs":"d4d27790c20eab0b16592f60d5e487425a45a268cf4c74cf843c10ac91bbff4c","src/internal.rs":"c3af5f53dc7957860bf3bc0cd9737d094fb8ac000e7b40c569304cfa76a43145","src/lib.rs":"cb49a3dd8782369172a2f8a61d5c74b4615bfb5fba3677af7d5c149e47d71815","src/log.rs":"6694178177775f2ce5449435d00609e9361c836e23119c07d04892000587dc55","src/macros.rs":"caef13f5d23f7a3ec1a54ec3ca2390ac4ad89d521893f1d0864daf70d57a20aa","src/mixer.rs":"e72e92855614da187da6419ed0a115062a05670cb73443b2ea4313d8f5108a68","src/panner.rs":"341af4b5a5331a3c1a4ab5396125a3600945e588ea33350431dfe6f1a9a0bd80","src/resampler.rs":"762070f8afde2256715b8764380cdfa1204a1a39d98a9da0b2efe88699792f2c","src/stream.rs":"7ca9f271b4556f31f6576edfc48a23af3e63dbfba3c5dd42f864e54a0e0a4d42"},"package":"318d9b60d6d5de52f815882ab5405adedc0ac7e91414950eff27a440c2860a3b"}
\ No newline at end of file
+{"files":{"Cargo.toml":"36f12dbd2d01bbf8ac6ff5ee25b5b28807860f7e77e830f483f31eb0cfa9b2bd","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","build.rs":"94f2df211c2ecff4f5be54a7aa12849fe973b555b0daa2a64493976db5be7dad","libcubeb/AUTHORS":"829e45d138c7c8827799f302806fa4be8cd8bd4bad70a2fe26c3a27a5cf36948","libcubeb/CMakeLists.txt":"1e66380904470ff3aa469a3a83ed21db4b68dd2414f66300a5956e972a8e68ca","libcubeb/Config.cmake.in":"88019286c96ef3d5d3a673b183c8655dfc97ceede07d3eb6c18f0c51bb896388","libcubeb/INSTALL.md":"7a84cdfbe86e7d3180e2203603b88571df61b369421fa97ee86740ffd4d4db8e","libcubeb/LICENSE":"44c6b5ae5ec3fe2fbc608b00e6f4896f4d2d5c7e525fcbaa3eaa3cf2f3d5a983","libcubeb/README.md":"aa417156dc65069264901b75fc3c792c73021ec61c909de04e109bd4184c07ab","libcubeb/TODO":"6f8065136e005d2becee810e3d8697a94f2c755f8c79687adfac7136ad165e80","libcubeb/appveyor.yml":"9a87fdc18b76fca1167289ecb2ec3a210b76984c1d7e92268b2cd36f1e00f541","libcubeb/cmake/sanitizers-cmake/CMakeLists.txt":"89b282c19b3897ff666f7847d5e679ae928ca7e76ffd0d23f7c58c9464048b61","libcubeb/cmake/sanitizers-cmake/LICENSE":"4b67e7ae8c91e68e1a929eb1cbaa4c773c6d19aa91aaa12c390cf9560d1c9799","libcubeb/cmake/sanitizers-cmake/README.md":"f3b85a594e1601ae65bb09393c56fbc8a98e3f3f49234e56f86bd78803c3544e","libcubeb/cmake/sanitizers-cmake/cmake/FindASan.cmake":"bd30b1c3cb0682b8a2b0b599f6c51fbf99ef4908b00eba8826f0d484c623b01b","libcubeb/cmake/sanitizers-cmake/cmake/FindMSan.cmake":"55e40f0994b47f8e779622af2007c69252d9456be99f4aa4fba7dd49c23d5580","libcubeb/cmake/sanitizers-cmake/cmake/FindSanitizers.cmake":"2ffd9717a49e3e9de848ec0d91097bdbab3f75a7866211d902f9659f59271ffc","libcubeb/cmake/sanitizers-cmake/cmake/FindTSan.cmake":"ceace234abd5a463ad1b8134ad06c4c8004895b2e8fc9edb67e64620ea97ca47","libcubeb/cmake/sanitizers-cmake/cmake/FindUBSan.cmake":"4720ec96ea42a2a9c07d887c1fc5562ed3e8c222f5778a18b78c46678b23f156","libcubeb/cmake/sanitizers-cmake/cmake/asan-wrapper":"4e543936e6374e24b80a0f92135c07c2e2101c0d110e51bddaf0e70ae8ec391e","libcubeb/cmake/sanitizers-cmake/cmake/sanitize-helpers.cmake":"c0c225f22bebd27eb68b807b2a61962d28afc61609735fe652c2fde6aa6a005b","libcubeb/cmake/sanitizers-cmake/tests/CMakeLists.txt":"64b7aea469a043f27414e3d652aaa89a03a11843d152c4cd42f30561e6ef51bc","libcubeb/cmake/sanitizers-cmake/tests/asan_test.cpp":"a25de95282aaee22d977d0b474468b946c1422b80b15424c04266dba038eba2e","libcubeb/cmake/sanitizers-cmake/tests/shortest.ext.test.cpp":"a25de95282aaee22d977d0b474468b946c1422b80b15424c04266dba038eba2e","libcubeb/cmake/toolchain-cross-mingw.cmake":"1c26749465364061ddf37aaa00f363eaf057c4b6a70181086e13b0a4d09bd376","libcubeb/cubeb.supp":"19f33e59f8dc91a327c923e44c2c3f9af0a043ce1d6a8cac275ba094b4bfe0da","libcubeb/docs/Doxyfile.in":"0815f19789cedd310652a133bab260c27b57e95f7a65458df2dfca38ea4f1041","libcubeb/googletest/CHANGES":"72c8a289bfe4dd9160074a3a2238c8067a5bc7ca49fd87f70a134c3f373932a4","libcubeb/googletest/CMakeLists.txt":"cdf938ce79ea066866dc614de3925bfaa48d9e19e04049db2ec8c5443abaaa9b","libcubeb/googletest/CONTRIBUTORS":"4d911cd5e6d71f3f4bbcb2788b2f916df4b0ce1e088752a159457a1d936ae0ce","libcubeb/googletest/COPYING":"9702de7e4117a8e2b20dafab11ffda58c198aede066406496bef670d40a22138","libcubeb/googletest/Makefile.am":"a795e5a18e82ba06fd97509d92d773b7fafd0dd7086db8a1211fbd151b503bac","libcubeb/googletest/README":"484b19654362942fac9734c8fab0ed3d99249b81c69027bdb7de46054abada6b","libcubeb/googletest/cmake/internal_utils.cmake":"6f4670a5825cf8ae0415be9dd43d82a7f30316d75cab20a4c60afb6d9db2a01d","libcubeb/googletest/codegear/gtest.cbproj":"9fa07a66b8c01773256e508187775407c465ed9055651e93d390426d1888721a","libcubeb/googletest/codegear/gtest.groupproj":"76c001cb2ee0070e26d1570fb6db5250f2585179c707496c5ef6d12e582cf205","libcubeb/googletest/codegear/gtest_all.cc":"c8750dc2b7b3612edb60e8d23fc2f60ae264451916c4b15f81cbf60ea30eb75d","libcubeb/googletest/codegear/gtest_link.cc":"e5e47c086f932471e0ca748a62b3b1597e5e731f4d34fb8cb8b2ca2db7ba3ed0","libcubeb/googletest/codegear/gtest_main.cbproj":"056448ba7f41fae3f704b1001922d9f6e419cf8cbcf3a55bf0ecc59ece1fa9a1","libcubeb/googletest/codegear/gtest_unittest.cbproj":"2c48be90b0dbc3224a8bd6c4dc21f78dd1b08c81685e6bd4952bb6df6ee38701","libcubeb/googletest/configure.ac":"fadebffdaeaccebb60fbe4a501c1138c296e01348a5da45fabf5e4233248baa8","libcubeb/googletest/include/gtest/gtest-death-test.h":"fdd087f700cd04a3ce4bdd36f35769de52a44bfc0c5bae2dc9681d4cbcd3c44a","libcubeb/googletest/include/gtest/gtest-message.h":"eaf44df1284d94333507c47091c84eaaf43814e6a02a1b1c0061ca7b363e74d6","libcubeb/googletest/include/gtest/gtest-param-test.h":"f226f0a24c04cddbceaaa45d8a5e575ce18c3392349f9b8ba73317e37e62368d","libcubeb/googletest/include/gtest/gtest-param-test.h.pump":"17c65fd5cc5218279044a61f3873c9c952b0924a7ba5147d4999d400b122207f","libcubeb/googletest/include/gtest/gtest-printers.h":"7046f611398d63ee0f1c37bdb4fd08d9931979b2fedf13b781e6d85d4b3b5d60","libcubeb/googletest/include/gtest/gtest-spi.h":"560407dd45e8e57fa6927504c9e4a4cfdecf30f8cada975c1ffddce765e6a88a","libcubeb/googletest/include/gtest/gtest-test-part.h":"c4d6d840284728740c284646075e8ffc85b63b9f74f3ed488b18ef3c2c2b9005","libcubeb/googletest/include/gtest/gtest-typed-test.h":"1ec858bbb9ed8a8bb553232df016437c080b2670f00453b4de297c286eb78c21","libcubeb/googletest/include/gtest/gtest.h":"47433ca72a43bda7a380c34fe6d4ff451797c687e9bbd74d1f366bcdfa0cb013","libcubeb/googletest/include/gtest/gtest_pred_impl.h":"f03a3f77e3c231889c0ace6f63b2c4e410e4a9330287ea09443b23b9a3cf9092","libcubeb/googletest/include/gtest/gtest_prod.h":"4a99a3d986a45b4d6d9b3af54809f015c54aa98274793a4ae173f5010d0ad33c","libcubeb/googletest/include/gtest/internal/gtest-death-test-internal.h":"0b3abead866363f3e6b4201acc8d2763072e033826b22ae5ebffd790e1415235","libcubeb/googletest/include/gtest/internal/gtest-filepath.h":"638d2bb6c06a894513b03311a8e931ac835fc00afc4bd21fab3afc05732c23a0","libcubeb/googletest/include/gtest/internal/gtest-internal.h":"12c2c83df0a9dc5b46697ccd8271dfa34ee5f3d1972dcb56585bc1459d9583c9","libcubeb/googletest/include/gtest/internal/gtest-linked_ptr.h":"9bd319548dd073630dfd349c06a440c6a582feec47d4ff14f348ec32f8b4c1f3","libcubeb/googletest/include/gtest/internal/gtest-param-util-generated.h":"10db93fa7e98820192bae6f560664469dd33b265036fca64253c89b6801f96cb","libcubeb/googletest/include/gtest/internal/gtest-param-util-generated.h.pump":"abb72365d94d2811b34c195dc520fbf41c7dcb42aae5a1cfa0502cf619b21e70","libcubeb/googletest/include/gtest/internal/gtest-param-util.h":"7f9311f033ef6916217d87cef53b1db6c4e8733be930e4b48fe7e11d21b33da0","libcubeb/googletest/include/gtest/internal/gtest-port.h":"612932c2930a7cf2c3514d89a8d6b51a2c0030d251309b71765ed1c9954e20c5","libcubeb/googletest/include/gtest/internal/gtest-string.h":"a46aa36165c400d1e926f942be03fe04cd7ccb1e59f7a2a03b919c4eea05b997","libcubeb/googletest/include/gtest/internal/gtest-tuple.h":"43e7e3c92f8e4258cf3927a9204b214d4d03e6c796f88f3ad4e66b1ac20aa938","libcubeb/googletest/include/gtest/internal/gtest-tuple.h.pump":"16fa027ed3c5940699e0ac906815e66620993bcf75b0acaf826d4f09348d4b83","libcubeb/googletest/include/gtest/internal/gtest-type-util.h":"6d177af46a9b1e14b969972a8b886667f95e69037aba411433a44fb9b92e7037","libcubeb/googletest/include/gtest/internal/gtest-type-util.h.pump":"22092f44127af91651f57ce222e20914d5d32ae02f1c0964f6d5d7bc019af339","libcubeb/googletest/m4/acx_pthread.m4":"3326e3746b6b351d1671fe31f798269cda8de92c365b8a8305404ec0fa6c6b32","libcubeb/googletest/m4/gtest.m4":"d3c37ebd1aa792c967d4357755cc670bc6deb30091d9e6db498871d90a30ea4c","libcubeb/googletest/make/Makefile":"9b86e2a112dd55c6bf6a2b39e6f4078faf60cfecb8282ebf9b025167ed233420","libcubeb/googletest/msvc/gtest-md.sln":"0beab679b42cf0c431eaf4fe143bbf3b01fc064e20c74d9e33e7e437a70487d4","libcubeb/googletest/msvc/gtest-md.vcproj":"52e873e964daf9d5409b4e9bb471ddf2827be04985cd96c40620f9275d17a256","libcubeb/googletest/msvc/gtest.sln":"be21c2340650ec2259a2fbaeb8608ae6d3e982a0626a0f91128a771dc88e6bea","libcubeb/googletest/msvc/gtest.vcproj":"0064616c7d88a284c1b7c05baab038f239134ea9c6c563628f286f9600b3f921","libcubeb/googletest/msvc/gtest_main-md.vcproj":"f83a294a92b616bf34ccae6743ff916297bdba61d6125a9637a813d467a30372","libcubeb/googletest/msvc/gtest_main.vcproj":"9f03270a00896eab0c7015c6fb1a73818d024e462d3944ba1d3ceb313a051649","libcubeb/googletest/msvc/gtest_prod_test-md.vcproj":"7caa108733e2d5f140da004d2133e04a9a105811909c0e2d4ec06e2971983592","libcubeb/googletest/msvc/gtest_prod_test.vcproj":"cf5bfb7f3de9a59a0eba5535067845d12c33c3fd8fecc3d03aa702665db29578","libcubeb/googletest/msvc/gtest_unittest-md.vcproj":"e7949b21cf0418f2a7afe8aa94616e2c40e3ba0801c2f0826f3a3a3d2e6f48b0","libcubeb/googletest/msvc/gtest_unittest.vcproj":"5b097d596fbbc1c4090fd518008a0961b29661194e1c02d8a2d3daaa557e626f","libcubeb/googletest/samples/prime_tables.h":"2903df1d1e6643a5f624fe3ea3f931c3410eb1858ac347c5df278273c6c91ca4","libcubeb/googletest/samples/sample1.cc":"dc106c5940d87bb4bbef3d77815eab642ee173a3340b2b9c532b5c711c4c2d0e","libcubeb/googletest/samples/sample1.h":"7a7bf9a0fbd2401e8b2cb554bfcb9bd0ed228212f3b970675c1b1d38d4e188bb","libcubeb/googletest/samples/sample10_unittest.cc":"ccebb6393a5a8468399f7e511219b667a2233f82312ce59834a4bb0997d8700e","libcubeb/googletest/samples/sample1_unittest.cc":"904be0d4a095e74393515195392bd10e1e916bb2ca61f3f94b1bd6aebea29cb6","libcubeb/googletest/samples/sample2.cc":"f14b8a1e69d52eef1a70053fb256818c7eca64e8eda08de43cf46e896e57fcc2","libcubeb/googletest/samples/sample2.h":"df956ba520dafca068dbc1e28f36567db3cba36293e06762318af8cda6a12bd4","libcubeb/googletest/samples/sample2_unittest.cc":"abe7e0b253d328cb82ae67623fbe3c89eb94699102510c64a0b568eaca101e05","libcubeb/googletest/samples/sample3-inl.h":"3fe482bbd4f725f5820f5d6beab4d0d4a524be8addf4b344a9a470ec5aabc451","libcubeb/googletest/samples/sample3_unittest.cc":"252c06b4531dc35213ebdd7311700b9b4057bc1bdeeba0cd767b2bc86c456639","libcubeb/googletest/samples/sample4.cc":"b4260f5fa35d78ac114a9abb59fce12403faf0273df41f57e83c341ae7979222","libcubeb/googletest/samples/sample4.h":"604905cae7e5587805c3b884a36eda7a2bebdfedb53b24b0fd9a220eec0ef1a9","libcubeb/googletest/samples/sample4_unittest.cc":"6cfb4821d8cb1c77fbb5af4f8aec569948762d8ea314827e3ead967b5b6a223e","libcubeb/googletest/samples/sample5_unittest.cc":"73646d9038873a68bb2e56b12495d7f7b65b5c23901109701da446af454ba2ec","libcubeb/googletest/samples/sample6_unittest.cc":"833fee399954f908cf0f3b789832e505329787f4cf73607a7b31ca0f62f368d7","libcubeb/googletest/samples/sample7_unittest.cc":"8013ee68d61c181e4e936cdae3a9a635646274f8512033ef11bff7214e03e4a6","libcubeb/googletest/samples/sample8_unittest.cc":"7b7510fadf4955d2f934d23d652dbd35add832e50bdfcc98421fb9be4588d808","libcubeb/googletest/samples/sample9_unittest.cc":"8b827040dea37b460cbcaea0b255b98974a9840f6ef7bd82aaa7d4ad2c724335","libcubeb/googletest/scripts/fuse_gtest_files.py":"adecf64c6bab65b31740c321e568cf174f753d5617745aa5762d842339d68b53","libcubeb/googletest/scripts/gen_gtest_pred_impl.py":"78fb7e20a014c251d723186eb58040e4eb32405b73c9288d787ea0a0e4ff5183","libcubeb/googletest/scripts/gtest-config.in":"9a43978eeee88e188845d737c17f4d024d4e74feae09da7997e8fbe4ea6cc176","libcubeb/googletest/scripts/pump.py":"3856a3d7be37f78e0f214ee7d4f29d05f1ca14218b67539d67c9a16e992f670c","libcubeb/googletest/scripts/test/Makefile":"3576b257594a2d8e843b9e4de8c83353d837833bb86431fb1b4198022b1bcddc","libcubeb/googletest/scripts/upload.py":"f75d0712e3b13bebd8daa0a15e4eb32c9e3034a933f4fcccf65b1e999a7ae066","libcubeb/googletest/scripts/upload_gtest.py":"6e76fc0a7a3831c01cfffd18c220d44438073a66338d91ca61fc84b924021e61","libcubeb/googletest/src/gtest-all.cc":"568ac119f5e6418f1fbcfbdf185d724657d7f3539b47822da229ac5d015626b2","libcubeb/googletest/src/gtest-death-test.cc":"eec1b3c8252670c76acbbaf63483946897ce625139b53a566406b6313f023896","libcubeb/googletest/src/gtest-filepath.cc":"31b7fcda5d11346f8a487597c6a70ff057f1192e0cb11f27eb7841a9f3aa8b86","libcubeb/googletest/src/gtest-internal-inl.h":"c9d428a6b5990ace091e40c4ce8b7bf6c50c186a8314b1c4a4cdc988ca0ac1a4","libcubeb/googletest/src/gtest-port.cc":"95bcf473622d1b901c734e5c2aeb8efb058555ec924212a61bb04f049bb5a069","libcubeb/googletest/src/gtest-printers.cc":"6f191a7fc7f5a0a967fd11964057f2e2d2eaf2f37ccece16bd816531f52b3154","libcubeb/googletest/src/gtest-test-part.cc":"e489868b4cdc66f4fc33bc2326ac86bc1acc5808ab58bbb288c9dcfc330faddc","libcubeb/googletest/src/gtest-typed-test.cc":"ca9e819df728c25a6a1fc072806c22f3494e1dffe4bd0d48284f38dbdd3a0dd5","libcubeb/googletest/src/gtest.cc":"5cf9a3e897892c9f0e5c887f91d3c8c8c5665bd7348560441fc0b946c254873c","libcubeb/googletest/src/gtest_main.cc":"22fa1f77542b882d1798d7f696045c5895942a626e26200a175fa4382e1fa5b5","libcubeb/googletest/test/gtest-death-test_ex_test.cc":"613ccf50a3ff8f84c975a13e86ea01ea4e36933072388a3738b4acf9ed3ed7cf","libcubeb/googletest/test/gtest-death-test_test.cc":"df8384a847bdf889233c3d45d171f784991def7a9b6a08442138569fbae32b9d","libcubeb/googletest/test/gtest-filepath_test.cc":"49760f91723845b113bb60bb9b1a1426ed1da1f4ebfef2462128980ea5692cc9","libcubeb/googletest/test/gtest-linked_ptr_test.cc":"1b9cb4ff67475900db9de34ae9749b94193048a1f7a741091ba5a2dd7fc7a79b","libcubeb/googletest/test/gtest-listener_test.cc":"acf78f2c9a730525ea5adc93e9196a42de8fbfe488db1dfd02656bdbd477b2c0","libcubeb/googletest/test/gtest-message_test.cc":"b1fc68f8b75ce25fbd79b3f7d3c9c793381ef07b3203e1a2d9b610cb597542be","libcubeb/googletest/test/gtest-options_test.cc":"74e3ae0c310edb3139b0032266219d3ce7f386ded6feafa57fef03f4493ed7fa","libcubeb/googletest/test/gtest-param-test2_test.cc":"a0f1efbcab3f7e49df639383157626931f64756f7e738be081760f93f7308332","libcubeb/googletest/test/gtest-param-test_test.cc":"ef8bd344e959053f562b0c9e0d15e2fb6c1e534772a67aaf3f90bd6bad0bf99f","libcubeb/googletest/test/gtest-param-test_test.h":"9d7f47b79d54df7cc050aa6038b0464aa684dfca669a847bf70ea16e4a000628","libcubeb/googletest/test/gtest-port_test.cc":"1600f78ef0860a0f5b5525e5e5041ff32a216cc6ae948b1ea61fe04ec603f67d","libcubeb/googletest/test/gtest-printers_test.cc":"7898e4b4163ee0821fed248e1c75d9f4a0a511a2b4bbfad1ef2f4a11a099f6e7","libcubeb/googletest/test/gtest-test-part_test.cc":"62c8906bb0d12ea84d60217b3773cd8e1768db4aab934880db2316df7026cab8","libcubeb/googletest/test/gtest-tuple_test.cc":"2850dc1f73a3f8020d8a4d80688a28d9b736eae6d677222c3f871d8d33b25501","libcubeb/googletest/test/gtest-typed-test2_test.cc":"c52b65e7181610d6e577631cd50177399884913ff28d08aedfedc92f05185044","libcubeb/googletest/test/gtest-typed-test_test.cc":"c7daff5211028da79b3ca0473dca18ada9197f38e710f72d0493ad3332ce3ec9","libcubeb/googletest/test/gtest-typed-test_test.h":"3145698534d8869beb624c9c8ed114f75bead046b2eeb92ada5a724993ee7786","libcubeb/googletest/test/gtest-unittest-api_test.cc":"e3f54c28ef2849e8b12af666ed46aace50c3e047845072ee6f974ce4528bd297","libcubeb/googletest/test/gtest_all_test.cc":"db0c3c42b385570b1d517e3ee927671b8fad4e206247fca738ec477222ac3d97","libcubeb/googletest/test/gtest_break_on_failure_unittest.py":"11c91bc1c68cfdb913e2affb01261b55fb3b0c18773a45875e9c25cb330a4dcd","libcubeb/googletest/test/gtest_break_on_failure_unittest_.cc":"1da12e4bdda2a0bc7b59d4638fe34b2d3798134224fd9237eeebdd09c3326011","libcubeb/googletest/test/gtest_catch_exceptions_test.py":"305cef45c6dc034bdf72fd91aba1e89e1c6b5d222c3d6baffff5acdfd9b3873e","libcubeb/googletest/test/gtest_catch_exceptions_test_.cc":"b297a4f4d5bc0285ea9eb8869741631658305e49d4513bca904842aacb82128b","libcubeb/googletest/test/gtest_color_test.py":"c4cb006682a40f2d88759a4bcabf0d4be623720b135c71447f1788d17ea23d0f","libcubeb/googletest/test/gtest_color_test_.cc":"f263ba349afe58a558bf0fee98a98bb9207a648e7cd4f908a87799bd13d001ea","libcubeb/googletest/test/gtest_env_var_test.py":"79819598cd1e366eaa8f2a4fee2d638b6ef0686e490402fae792ccce58d876c0","libcubeb/googletest/test/gtest_env_var_test_.cc":"0eee5dfbb2a2598f4e76626346b921928ec1e052e38f254cc97c60d05611ab46","libcubeb/googletest/test/gtest_environment_test.cc":"a52a21ea29c2203b03fa93922733546d171f98d3b2fcd42972269e98fd124715","libcubeb/googletest/test/gtest_filter_unittest.py":"edc7d278803bba41626eacd050d91d7247f1c5999f9dceb99a8877e238bc73d6","libcubeb/googletest/test/gtest_filter_unittest_.cc":"996ac528ad75c293d8201ce28cf6acccee266286bd369b4cf43f05b8d67a4559","libcubeb/googletest/test/gtest_help_test.py":"b43ab690c08e4bffd84a47b361167496298697f9511bdf4a745bf305b5cfbdfc","libcubeb/googletest/test/gtest_help_test_.cc":"ff4b121098f0fe7cb4abf11fdd31f2fe7a477286ec9175482138bc038d61c807","libcubeb/googletest/test/gtest_list_tests_unittest.py":"7caebc175b44b3c727fc50420ada1a6a9500f3e4ce9e2839f69205437aa85e7a","libcubeb/googletest/test/gtest_list_tests_unittest_.cc":"d82d8b72914897232c2ff9fd091a7b0add68b7cf75f3f210d3a487ebeea84cfe","libcubeb/googletest/test/gtest_main_unittest.cc":"0f66f318809c88f0fbe034a340a75331720c4e33be5378022baffaf588ef1202","libcubeb/googletest/test/gtest_no_test_unittest.cc":"7cf487e07c3d27376c2cb8af33d02239b7966623875d37b7aa0259e927a9c2f6","libcubeb/googletest/test/gtest_output_test.py":"cf0dc1979572d94450a5e611b44f3fdb88d9cd980d669a723f0ed63057b5e2c4","libcubeb/googletest/test/gtest_output_test_.cc":"f69569374c2b3d06aa04a38ebc4f92ddc303e6af503f8b533cd8e6bf9f104899","libcubeb/googletest/test/gtest_output_test_golden_lin.txt":"4f3e49c10a524a99437cdcb5294e3335a7f3c07ea8462e65730f703a5fe4fec3","libcubeb/googletest/test/gtest_pred_impl_unittest.cc":"e406eccf75b6b58746a95d1c7ea7bc8e80ff974e438ef7c83074a46d4e62db9a","libcubeb/googletest/test/gtest_prod_test.cc":"b42ca1a6d0a1e43bc576b4ff7776c6d2c37234f6dc2a76f2735f261b4a47a526","libcubeb/googletest/test/gtest_repeat_test.cc":"e10abbb71595920aa3bb415029eed74106335fc9ea3d58c417ccfc7cba6a4cdb","libcubeb/googletest/test/gtest_shuffle_test.py":"12dd94eb5f30260ba37059fa74658bda57dffa821f3ba6a2a8b52ff14b1ad029","libcubeb/googletest/test/gtest_shuffle_test_.cc":"af1b2b01ae275f1a9fee7e7940c0f88f39ded063008994d585aad87e3ffadb39","libcubeb/googletest/test/gtest_sole_header_test.cc":"538414c27a593ab8dc34c37b5c877eb3a022d75d1b481ef14ceca00914929754","libcubeb/googletest/test/gtest_stress_test.cc":"0b02fc12f87944226915a999bdcc8a3eaafb34a1ea5bb0df128774abf8667f09","libcubeb/googletest/test/gtest_test_utils.py":"d4a76930aee6658ad8734981ca0c4ea14f34dbe8fdd31d5afe41f6d98f9779ee","libcubeb/googletest/test/gtest_throw_on_failure_ex_test.cc":"11ae790028da20bc7b7af1572eff3cfe8499be43ab64c110e18e1892612a183f","libcubeb/googletest/test/gtest_throw_on_failure_test.py":"ebe18ca0b07f90c53b9b3f9a54ed02df94facf8995cfa90dd41c6f5474537c13","libcubeb/googletest/test/gtest_throw_on_failure_test_.cc":"f8cbf75d8bf9e9ae068a17ff968434c3aec7b7f1137c994d8f14af1a84361aa9","libcubeb/googletest/test/gtest_uninitialized_test.py":"da8e6ce34930753e36fc1dfa2c3e20e48d02bda2a27d3d03a07364312c5f3bd9","libcubeb/googletest/test/gtest_uninitialized_test_.cc":"0b6a9d4983480f87352ca4da946089264b401f7a4a3b1282253fd6cc861bf483","libcubeb/googletest/test/gtest_unittest.cc":"c0c7d1f691ce1e10c3d1647ed5f7a66510725808ad58bb6da4bc03a7a08fb2fc","libcubeb/googletest/test/gtest_xml_outfile1_test_.cc":"29341d777a9c9d25f360d13ed966b30f0cbef1fc88aefe2f01bb88b82cf1ed93","libcubeb/googletest/test/gtest_xml_outfile2_test_.cc":"da7ab3cf0e9b2a293eceed7c5691233d6b61afb557e3c1176dfb75390f85be46","libcubeb/googletest/test/gtest_xml_outfiles_test.py":"b07927b43f44afbfd61761c2cc69f1b68c4fbdeddb992db03ff0c73052518cd4","libcubeb/googletest/test/gtest_xml_output_unittest.py":"b5ff0c0207238d01cada961b8f4656f2ec30a3e1e5bf9d22efdf1745af423031","libcubeb/googletest/test/gtest_xml_output_unittest_.cc":"ad0b9ebe63a146e386df3c5c51916869f6d4647b9832ceacc912fb1272d15f82","libcubeb/googletest/test/gtest_xml_test_utils.py":"ad89a39a6cd5b08e87082341f3e7800dbf1150ea0f1386e0b8cd374aa6832f00","libcubeb/googletest/test/production.cc":"56fef77c3a8e62073ec11653d740a8e534008a0d57925ab0877b843f4fdd6be8","libcubeb/googletest/test/production.h":"a36d10545d12ead5e93a3b0fdca6ff73405f29091cfe38164415e9038888ba8d","libcubeb/googletest/xcode/Config/DebugProject.xcconfig":"fb42302df29bd8e8b5237194c0c04941f0e578527037930d88469baeb7a7f62b","libcubeb/googletest/xcode/Config/FrameworkTarget.xcconfig":"9935ddabe221f074d2f3b969a137d12b0dc0f845a460f58b63232987cb0f37ff","libcubeb/googletest/xcode/Config/General.xcconfig":"0fb768924daba1048f8db28b3a1fbf915b6f788d49d9d37e85979aa4ee92e02d","libcubeb/googletest/xcode/Config/ReleaseProject.xcconfig":"a4878ddd1ed78fb411906623cb51bc0ab4aea1cc3feb5379d2ae2862d8bf3bf5","libcubeb/googletest/xcode/Config/StaticLibraryTarget.xcconfig":"5886291788b3e9d5aadcb979ff055fd26a2413be81016e7afffb813b627d177c","libcubeb/googletest/xcode/Config/TestTarget.xcconfig":"f074e6c2516a6063b253ec6b842d74f5c2abefc7bcf8d8da54097a7bfe016480","libcubeb/googletest/xcode/Resources/Info.plist":"5b7f78a6d5810ce5490649793175c8982d41e6b49af06bc0705bc061567cc9aa","libcubeb/googletest/xcode/Samples/FrameworkSample/Info.plist":"1c13d83e5eed45689d7fe4bf4681030366474bc40608e39e1623c1350513a0cd","libcubeb/googletest/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj":"1cf0e1b1abf84414372faf9c8bf634e01fe5750bb3ca769b1eb25fc530b21358","libcubeb/googletest/xcode/Samples/FrameworkSample/runtests.sh":"a587e5b00a8353dee0aca5a4c59b28301ccf7648dee8c79b62a9223f9fc3c8cf","libcubeb/googletest/xcode/Samples/FrameworkSample/widget.cc":"562a2bb615e93186012823c9b41761769638a11e38b54498ad5f699038c8fd32","libcubeb/googletest/xcode/Samples/FrameworkSample/widget.h":"0c7915e45cf7cb8d67db24e49cd0b277f23f967578f917f8e859a6adc4b156f9","libcubeb/googletest/xcode/Samples/FrameworkSample/widget_test.cc":"6a1a49d64912d9829ef3d991faf5a3f0e1e081126a1d8d387cdfa84fab70dc77","libcubeb/googletest/xcode/Scripts/runtests.sh":"1a0672a4151b16f3c797478ba26c534e82b2faa603f90b9aa14e785805f7683a","libcubeb/googletest/xcode/Scripts/versiongenerate.py":"4b9d5c0f4e1b556084109311d156bee6d781968dc5b1dfdc8702364508f1dd43","libcubeb/googletest/xcode/gtest.xcodeproj/project.pbxproj":"a1224decff058bfed01b8eefaee13cab0129492615548c6d0d878003a154f7ff","libcubeb/include/cubeb/cubeb.h":"6dca4f874a188e6bd7e476c22418a7e011d6fefd77cb9cce5d061c9ef527f29a","libcubeb/scan-build-install.sh":"1ecf22aca367a4d02f810c4cb78db8636e08a12787e94e30c441ce439cf4a265","libcubeb/src/android/audiotrack_definitions.h":"0d5ec772f9ebf61333bc16e61a081a7e3b4cc02342ec4f8f417e220d032fbbc6","libcubeb/src/android/cubeb-output-latency.h":"000fb7bec38105f54b9d40fc436440c637d63390b219775d335216d29d767226","libcubeb/src/android/cubeb_media_library.h":"f67965fb2ea38f0023eb4c76024341ba9563ac1a135507b6f12a9aabd85e30a9","libcubeb/src/android/sles_definitions.h":"66d10b157e463ee106236736b0338d1ec512d66d577ecafda56427bf14658443","libcubeb/src/cubeb-internal.h":"e58ce40e1402a8fbbbc048b453f01868174aac191b6cc8b66be7ceb0141cc2c4","libcubeb/src/cubeb-jni-instances.h":"8195554372bf60dea569873c9e5fb1106a2cf5dedc66a13d2bc967da0ff48a12","libcubeb/src/cubeb-jni.cpp":"81f001720c41c69b5927e32bd19b9e8e7176d7c33d63c2a58bd0d695dace4fd2","libcubeb/src/cubeb-jni.h":"73f810a32087a6062fd49ba89542655a7e19cecac6f40f8411e1d77ce42a45d1","libcubeb/src/cubeb-sles.h":"dc84a01ba4de9db1ff108609930b36ba442020ccc3e3d6f16528f429426c430c","libcubeb/src/cubeb-speex-resampler.h":"dbf543eee4cc6e40ba3531a39d327e2cec884c19e26c570aa7eae0647e5f7420","libcubeb/src/cubeb.c":"b8f8e5ffd028aa2d50745f26ee69b51e476576724c0d67534029370310ab9caf","libcubeb/src/cubeb_alsa.c":"4ae98dfc610a5f0814aa8dd9eac3c05eca72fba59fb2025239f4f336847c9e63","libcubeb/src/cubeb_array_queue.h":"5264ae02799c540ff73e8eb8efa55986772b22562a025ae227c2603b6b8d1036","libcubeb/src/cubeb_assert.h":"ab8ed4fe7070a3aed9419c5f9695fce2318c4dafd91213ae61cac476e64adaa7","libcubeb/src/cubeb_audiotrack.c":"04bb993fc2a8dfaaca6f7930370111fdc1b072f054b1e4d7c34658cabd107fd8","libcubeb/src/cubeb_audiounit.cpp":"9ad755c93b2a4893e59547d7089ebe95207dd8e4dd8a2741150dc5759bd0146b","libcubeb/src/cubeb_jack.cpp":"1e4676767720df3599f424e6973660e11011b79d89faa4bfdd5910f30a65ceb0","libcubeb/src/cubeb_kai.c":"068d48462f3263013aa59aff589039a334c5cd4eab4254f8011e4bb60afeadbd","libcubeb/src/cubeb_log.cpp":"74bdc0d92a31d6b4ce3c376c6d310db583b869d673e40e6bd0ea795a1e2f937a","libcubeb/src/cubeb_log.h":"ee05fd22ed9820bed79247b8603cdc64f67bcb145be47e78bf0a0e99fb6c0806","libcubeb/src/cubeb_mixer.cpp":"061427a06516792ead3936a643224c3d275913410f67765cc24e1b8699e8d99d","libcubeb/src/cubeb_mixer.h":"e94205c1b98859e41eeab2cad53f635f34f57a2ae95aa23a36461a2619abf81b","libcubeb/src/cubeb_opensl.c":"cfd2e5a53a8e10f54ab4e7259ebc9ee5034bf5958642a28527d7397aa5bb4b2f","libcubeb/src/cubeb_osx_run_loop.cpp":"13c029f7ea04808597b8841b13f248c4476fb7425762f01a59bc6c944cab3a78","libcubeb/src/cubeb_osx_run_loop.h":"ffe80df60b8ea3d0341715b72cc60aae2e0df45141887c01117df543260a0ef8","libcubeb/src/cubeb_pulse.c":"dec7a5a31942f343ab47b90974aed66bb7bdcc17a1d256edcf403aefaec8b01c","libcubeb/src/cubeb_resampler.cpp":"f58deac4d17f004e8b31773335bb0cafbde08494cbda8453fa39a36617e47337","libcubeb/src/cubeb_resampler.h":"ad9800a40c0272fb2a451c02367cc5a516a3067d4acf963d35eb31be367f9224","libcubeb/src/cubeb_resampler_internal.h":"4b4eb6aee343b9c1f73cf17b201329d3714ba44b06ecb1cebf950fdf93a9dfe6","libcubeb/src/cubeb_ring_array.h":"db8dec7a6d778a424045e5ac61c2bc3a3cec8c4fe8e4780f383db4b6f1b2438c","libcubeb/src/cubeb_ringbuffer.h":"2296255ca7835a3ace2fe1852054f43428b677f432b4174bd832ad0224a409eb","libcubeb/src/cubeb_sndio.c":"0037a0bb173ad9b0302e3cc24edc5062d6a37dc4d2505d035282043d99e61c5b","libcubeb/src/cubeb_strings.c":"60f2b8c03a5a01925f9777eec0ab84b0e704b40c03e0d6b9c0e7a16246c81fde","libcubeb/src/cubeb_strings.h":"00e5dc97cf16e28cfb53aaae50ac0e3c0ae8a82aad0720ab6842ce5d9785c39f","libcubeb/src/cubeb_sun.c":"3af2394c4d3575ef2c7862549789eda29a61a4a00646e18299edaa1c72259daf","libcubeb/src/cubeb_utils.cpp":"5bd7de8bbf7bbdc3a275525edd92bad590fb90fb4d35e77017fdd5d25a5769e6","libcubeb/src/cubeb_utils.h":"27baa42747771bf9232741382b83722f5c731e5dcd4dc2e9b595aca91c5647a5","libcubeb/src/cubeb_utils_unix.h":"2a48bd2aefa1b4e4e4968121512bcaaa6be3bca6597ea390b8203c338f5c49b5","libcubeb/src/cubeb_utils_win.h":"74658b6266a8a223c681b0fd06fcc9c891c7b0b95377635c6f1763b240c2ab27","libcubeb/src/cubeb_wasapi.cpp":"bccff541f927f6cf436806a3b04c4fc97d001dc2119279ed62bf27c18f6d8bcd","libcubeb/src/cubeb_winmm.c":"7416b044d333892e79489a2b3d787ef50bf9ea65db99cbe03885b04967df9b7c","libcubeb/src/speex/arch.h":"2300bce68c588270cdc684dc7f01377e5e251529f4545d93771e111c56d51b0f","libcubeb/src/speex/fixed_generic.h":"306ee7453677fa6067f16c79d358c6c90a9d3d008850b493cdaa59c07e6375c1","libcubeb/src/speex/resample.c":"9c3a1c64ecf3750af82c980d01ea73d3682f73c332a580465d1e787e5c54cd00","libcubeb/src/speex/resample_neon.h":"7d3fd7af9a1ddde22518b9c7b4419073b72b2dfa5be4c3bc8796992bc87b3da0","libcubeb/src/speex/resample_sse.h":"5a196d8e2d8ab5c956f5252f09f5ddc55aee1f99b1341af3fa54a1f4c2157924","libcubeb/src/speex/speex_config_types.h":"24e3ffbf29e5519611a48e5acb959645b01d166dcb4369380d5f776c3f53d4cd","libcubeb/src/speex/speex_resampler.h":"7e439ec0dd30c32216b3ced17135f8992e5aaf53389d3f5996a7d900c453e65f","libcubeb/src/speex/stack_alloc.h":"e8a2fc0874942d2c7177475fcc141fdd0c0156200b8a4e7656d4a20313e2e569","libcubeb/test/README.md":"1c11b038f87daf10ea78abc17bdbdd157940c241df548c24d5872d142a98c1af","libcubeb/test/common.h":"968144634f3ce627d7f6cb91d48ddc6f1fa89f481ae63f80a7cbe743989e449c","libcubeb/test/test_audio.cpp":"4dfa5e686293101541a300b04712f0cd5a32904fc1f1a71f73ca872d56050e57","libcubeb/test/test_callback_ret.cpp":"f2d190ec14b2da927bb4cd759f775cd3b7f38df3cd2984862b346f7c37eb9ca8","libcubeb/test/test_deadlock.cpp":"0e28e59f360e27241536879d9e02e4e05291db252f66fd601577aaf723e06543","libcubeb/test/test_device_changed_callback.cpp":"c30bcd2ec4348f56c520952cef18a47c430f121cad59d64d648498c14e79f080","libcubeb/test/test_devices.cpp":"8c61e4319af2af5a59103fccd216c666424d42b859b8719166513e26eebd39c3","libcubeb/test/test_duplex.cpp":"fa9944a3d7975b21ad0b61690f2ab40c4ed16a4c3f2758d7b6ad0df60cbb0768","libcubeb/test/test_latency.cpp":"dc5af071df0ff0c4b2f6cf7b37438ac8ed9f18cc0fafffb2c685b1e82201c9f5","libcubeb/test/test_loopback.cpp":"f67c2828e2e238f07a0d1371d42ae916b9d7decfc4233fcf4d632346ef98871d","libcubeb/test/test_overload_callback.cpp":"f3ffa014a0e6f7871a023b46733f93d992ddc9b41e0974cc22a365979b6d989e","libcubeb/test/test_record.cpp":"89a884872b780005b2fb29d106b6f33ddd76b2fcae381395e17d3413153b3b89","libcubeb/test/test_resampler.cpp":"ca4bc0493ce0c3a5f02f389ac6e37bc2cdb9a752faad2b6fbc5af0a2223ef645","libcubeb/test/test_ring_array.cpp":"27836d716616abf8b020a710659c10ac5e1d4b64149d22cb89bd7a7a5a5669d1","libcubeb/test/test_ring_buffer.cpp":"4ca684e38f1d34bb1f625ce2a2a730e5b24e09d1107f108e8b80731e55315861","libcubeb/test/test_sanity.cpp":"19e2b22e50fef3120859bfe9e9c5fcf5720b47e694eb02c9cd388c3345706ea2","libcubeb/test/test_tone.cpp":"02de19023d203e2d538c4f8ae23574153a4df6ada1d06fb83af2d51603b61669","libcubeb/test/test_utils.cpp":"e8d7a02a9096dbc0fd15d71f9849415d52958d2ed82cbc7b8507d3228e08d382","libcubeb/tools/cubeb-test.cpp":"112ecc87060761e31c4fa181de3c17fd91f0d0a135f6e1085f0f6a0331933fdb","src/callbacks.rs":"b4b4eb3f370475488d7c77b338b0bceee94ef59ede8ff41fa797a3d35ea98b5d","src/channel.rs":"555bc8d5257496cf6e5b4c786df84755327d88a9dc07202746e35f3b7b7e4e0b","src/context.rs":"96bf3442b1dd40262d3088dbb6c473f5451fd91320cef93c522b40f284599803","src/device.rs":"5b65e1c1fdd53fa5208f20bfb809475cbb3c434e02db7d0e4771d13c86f8e369","src/error.rs":"406e3b843ed2d263fe677c4b34fb96a6d780a68bcb56a6f85f041d20d70227bd","src/format.rs":"d4d27790c20eab0b16592f60d5e487425a45a268cf4c74cf843c10ac91bbff4c","src/internal.rs":"c3af5f53dc7957860bf3bc0cd9737d094fb8ac000e7b40c569304cfa76a43145","src/lib.rs":"cdc36b11f18e274d10df592d216f142e05e1d22db5aac4c7e346893d6b1510db","src/log.rs":"6694178177775f2ce5449435d00609e9361c836e23119c07d04892000587dc55","src/macros.rs":"caef13f5d23f7a3ec1a54ec3ca2390ac4ad89d521893f1d0864daf70d57a20aa","src/mixer.rs":"e72e92855614da187da6419ed0a115062a05670cb73443b2ea4313d8f5108a68","src/resampler.rs":"762070f8afde2256715b8764380cdfa1204a1a39d98a9da0b2efe88699792f2c","src/stream.rs":"c4e102bf8ca9c63144346342ab2668b6f554969eb0f6bae96a58eb0420534adf"},"package":"309c5839c5fa03c08363bd308566cbe4654b25a9984342d7546a33d55b80a3d6"}
\ No newline at end of file
--- a/third_party/rust/cubeb-sys/Cargo.toml
+++ b/third_party/rust/cubeb-sys/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 = "cubeb-sys"
-version = "0.5.5"
+version = "0.6.2"
 authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"]
 build = "build.rs"
 links = "cubeb"
 description = "Native bindings to the cubeb library"
 license = "ISC"
 repository = "https://github.com/djg/cubeb-rs"
 [build-dependencies.cmake]
 version = "0.1.2"
--- a/third_party/rust/cubeb-sys/build.rs
+++ b/third_party/rust/cubeb-sys/build.rs
@@ -63,16 +63,17 @@ fn main() {
         println!("cargo:rustc-link-lib=framework=CoreAudio");
         println!("cargo:rustc-link-lib=framework=CoreServices");
         println!("cargo:rustc-link-lib=dylib=c++");
         println!("cargo:rustc-link-search=native={}/lib", dst.display());
     } else {
         println!("cargo:rustc-link-lib=static=cubeb");
         println!("cargo:rustc-link-lib=dylib=stdc++");
         println!("cargo:rustc-link-search=native={}/lib", dst.display());
+        println!("cargo:rustc-link-search=native={}/lib64", dst.display());
 
         // Ignore the result of find_library. We don't care if the
         // libraries are missing.
         let _ = pkg_config::find_library("alsa");
         let _ = pkg_config::find_library("libpulse");
         let _ = pkg_config::find_library("jack");
     }
 }
--- a/third_party/rust/cubeb-sys/libcubeb/CMakeLists.txt
+++ b/third_party/rust/cubeb-sys/libcubeb/CMakeLists.txt
@@ -62,17 +62,16 @@ if(NOT MSVC)
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter")
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter")
 endif()
 
 add_library(cubeb
   src/cubeb.c
   src/cubeb_mixer.cpp
   src/cubeb_resampler.cpp
-  src/cubeb_panner.cpp
   src/cubeb_log.cpp
   src/cubeb_strings.c
   src/cubeb_utils.cpp
    $<TARGET_OBJECTS:speex>)
 target_include_directories(cubeb
   PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>
 )
 target_include_directories(cubeb PRIVATE src)
@@ -151,17 +150,17 @@ if(USE_AUDIOUNIT)
   target_link_libraries(cubeb PRIVATE "-framework AudioUnit" "-framework CoreAudio" "-framework CoreServices")
 endif()
 
 check_include_files(pulse/pulseaudio.h USE_PULSE)
 if(USE_PULSE)
   target_sources(cubeb PRIVATE
     src/cubeb_pulse.c)
   target_compile_definitions(cubeb PRIVATE USE_PULSE)
-  target_link_libraries(cubeb PRIVATE pulse)
+  target_link_libraries(cubeb PRIVATE pulse pthread)
   if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
     target_link_libraries(cubeb PRIVATE dl)
   endif()
 endif()
 
 check_include_files(alsa/asoundlib.h USE_ALSA)
 if(USE_ALSA)
   target_sources(cubeb PRIVATE
@@ -251,17 +250,17 @@ if(USE_PULSE_RUST)
     BUILD_COMMAND cargo build COMMAND cargo build --release
     BINARY_DIR "${CMAKE_SOURCE_DIR}/src/cubeb-pulse-rs"
     INSTALL_COMMAND ""
     LOG_BUILD ON)
   add_dependencies(cubeb cubeb_pulse_rs)
   target_compile_definitions(cubeb PRIVATE USE_PULSE_RUST)
   target_link_libraries(cubeb PRIVATE
     debug "${CMAKE_SOURCE_DIR}/src/cubeb-pulse-rs/target/debug/libcubeb_pulse.a"
-    optimized "${CMAKE_SOURCE_DIR}/src/cubeb-pulse-rs/target/release/libcubeb_pulse.a")
+    optimized "${CMAKE_SOURCE_DIR}/src/cubeb-pulse-rs/target/release/libcubeb_pulse.a" pulse)
 endif()
 
 if(USE_AUDIOUNIT_RUST)
   include(ExternalProject)
   set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/rust)
   ExternalProject_Add(
     cubeb_coreaudio_rs
     DOWNLOAD_COMMAND ""
--- a/third_party/rust/cubeb-sys/libcubeb/include/cubeb/cubeb.h
+++ b/third_party/rust/cubeb-sys/libcubeb/include/cubeb/cubeb.h
@@ -563,30 +563,16 @@ CUBEB_EXPORT int cubeb_stream_get_latenc
     @param stream the stream for which to adjust the volume.
     @param volume a float between 0.0 (muted) and 1.0 (maximum volume)
     @retval CUBEB_OK
     @retval CUBEB_ERROR_INVALID_PARAMETER volume is outside [0.0, 1.0] or
             stream is an invalid pointer
     @retval CUBEB_ERROR_NOT_SUPPORTED */
 CUBEB_EXPORT int cubeb_stream_set_volume(cubeb_stream * stream, float volume);
 
-/** If the stream is stereo, set the left/right panning. If the stream is mono,
-    this has no effect.
-    @param stream the stream for which to change the panning
-    @param panning a number from -1.0 to 1.0. -1.0 means that the stream is
-           fully mixed in the left channel, 1.0 means the stream is fully
-           mixed in the right channel. 0.0 is equal power in the right and
-           left channel (default).
-    @retval CUBEB_OK
-    @retval CUBEB_ERROR_INVALID_PARAMETER if stream is null or if panning is
-            outside the [-1.0, 1.0] range.
-    @retval CUBEB_ERROR_NOT_SUPPORTED
-    @retval CUBEB_ERROR stream is not mono nor stereo */
-CUBEB_EXPORT int cubeb_stream_set_panning(cubeb_stream * stream, float panning);
-
 /** Get the current output device for this stream.
     @param stm the stream for which to query the current output device
     @param device a pointer in which the current output device will be stored.
     @retval CUBEB_OK in case of success
     @retval CUBEB_ERROR_INVALID_PARAMETER if either stm, device or count are
             invalid pointers
     @retval CUBEB_ERROR_NOT_SUPPORTED */
 CUBEB_EXPORT int cubeb_stream_get_current_device(cubeb_stream * stm,
--- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb-internal.h
+++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb-internal.h
@@ -59,17 +59,16 @@ struct cubeb_ops {
                       void * user_ptr);
   void (* stream_destroy)(cubeb_stream * stream);
   int (* stream_start)(cubeb_stream * stream);
   int (* stream_stop)(cubeb_stream * stream);
   int (* stream_reset_default_device)(cubeb_stream * stream);
   int (* stream_get_position)(cubeb_stream * stream, uint64_t * position);
   int (* stream_get_latency)(cubeb_stream * stream, uint32_t * latency);
   int (* stream_set_volume)(cubeb_stream * stream, float volumes);
-  int (* stream_set_panning)(cubeb_stream * stream, float panning);
   int (* stream_get_current_device)(cubeb_stream * stream,
                                     cubeb_device ** const device);
   int (* stream_device_destroy)(cubeb_stream * stream,
                                 cubeb_device * device);
   int (* stream_register_device_changed_callback)(cubeb_stream * stream,
                                                   cubeb_device_changed_callback device_changed_callback);
   int (* register_device_collection_changed)(cubeb * context,
                                              cubeb_device_type devtype,
--- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb.c
+++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb.c
@@ -69,17 +69,17 @@ int kai_init(cubeb ** context, char cons
 
 static int
 validate_stream_params(cubeb_stream_params * input_stream_params,
                        cubeb_stream_params * output_stream_params)
 {
   XASSERT(input_stream_params || output_stream_params);
   if (output_stream_params) {
     if (output_stream_params->rate < 1000 || output_stream_params->rate > 192000 ||
-        output_stream_params->channels < 1) {
+        output_stream_params->channels < 1 || output_stream_params->channels > UINT8_MAX) {
       return CUBEB_ERROR_INVALID_FORMAT;
     }
   }
   if (input_stream_params) {
     if (input_stream_params->rate < 1000 || input_stream_params->rate > 192000 ||
         input_stream_params->channels < 1 || input_stream_params->channels > 8) {
       return CUBEB_ERROR_INVALID_FORMAT;
     }
@@ -429,29 +429,16 @@ cubeb_stream_set_volume(cubeb_stream * s
 
   if (!stream->context->ops->stream_set_volume) {
     return CUBEB_ERROR_NOT_SUPPORTED;
   }
 
   return stream->context->ops->stream_set_volume(stream, volume);
 }
 
-int cubeb_stream_set_panning(cubeb_stream * stream, float panning)
-{
-  if (!stream || panning < -1.0 || panning > 1.0) {
-    return CUBEB_ERROR_INVALID_PARAMETER;
-  }
-
-  if (!stream->context->ops->stream_set_panning) {
-    return CUBEB_ERROR_NOT_SUPPORTED;
-  }
-
-  return stream->context->ops->stream_set_panning(stream, panning);
-}
-
 int cubeb_stream_get_current_device(cubeb_stream * stream,
                                     cubeb_device ** const device)
 {
   if (!stream || !device) {
     return CUBEB_ERROR_INVALID_PARAMETER;
   }
 
   if (!stream->context->ops->stream_get_current_device) {
--- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_alsa.c
+++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_alsa.c
@@ -1364,14 +1364,13 @@ static struct cubeb_ops const alsa_ops =
   .stream_init = alsa_stream_init,
   .stream_destroy = alsa_stream_destroy,
   .stream_start = alsa_stream_start,
   .stream_stop = alsa_stream_stop,
   .stream_reset_default_device = NULL,
   .stream_get_position = alsa_stream_get_position,
   .stream_get_latency = alsa_stream_get_latency,
   .stream_set_volume = alsa_stream_set_volume,
-  .stream_set_panning = NULL,
   .stream_get_current_device = NULL,
   .stream_device_destroy = NULL,
   .stream_register_device_changed_callback = NULL,
   .register_device_collection_changed = NULL
 };
--- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_audiotrack.c
+++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_audiotrack.c
@@ -429,14 +429,13 @@ static struct cubeb_ops const audiotrack
   .stream_init = audiotrack_stream_init,
   .stream_destroy = audiotrack_stream_destroy,
   .stream_start = audiotrack_stream_start,
   .stream_stop = audiotrack_stream_stop,
   .stream_reset_default_device = NULL,
   .stream_get_position = audiotrack_stream_get_position,
   .stream_get_latency = audiotrack_stream_get_latency,
   .stream_set_volume = audiotrack_stream_set_volume,
-  .stream_set_panning = NULL,
   .stream_get_current_device = NULL,
   .stream_device_destroy = NULL,
   .stream_register_device_changed_callback = NULL,
   .register_device_collection_changed = NULL
 };
--- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_audiounit.cpp
+++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_audiounit.cpp
@@ -18,17 +18,16 @@
 #include <CoreAudio/HostTime.h>
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 #include <CoreAudio/CoreAudioTypes.h>
 #include <AudioToolbox/AudioToolbox.h>
 #include "cubeb/cubeb.h"
 #include "cubeb-internal.h"
 #include "cubeb_mixer.h"
-#include "cubeb_panner.h"
 #if !TARGET_OS_IPHONE
 #include "cubeb_osx_run_loop.h"
 #endif
 #include "cubeb_resampler.h"
 #include "cubeb_ring_array.h"
 #include <algorithm>
 #include <atomic>
 #include <vector>
@@ -56,17 +55,17 @@ const char * PRIVATE_AGGREGATE_DEVICE_NA
 #ifdef ALOG
 #undef ALOG
 #endif
 #define ALOG(msg, ...) dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{LOG(msg, ##__VA_ARGS__);})
 
 /* Testing empirically, some headsets report a minimal latency that is very
  * low, but this does not work in practice. Lie and say the minimum is 256
  * frames. */
-const uint32_t SAFE_MIN_LATENCY_FRAMES = 256;
+const uint32_t SAFE_MIN_LATENCY_FRAMES = 128;
 const uint32_t SAFE_MAX_LATENCY_FRAMES = 512;
 
 const AudioObjectPropertyAddress DEFAULT_INPUT_DEVICE_PROPERTY_ADDRESS = {
   kAudioHardwarePropertyDefaultInputDevice,
   kAudioObjectPropertyScopeGlobal,
   kAudioObjectPropertyElementMaster
 };
 
@@ -236,17 +235,17 @@ struct cubeb_stream {
   atomic<int64_t> frames_written{ 0 };
   atomic<bool> shutdown{ true };
   atomic<bool> draining{ false };
   atomic<bool> reinit_pending { false };
   atomic<bool> destroy_pending{ false };
   /* Latency requested by the user. */
   uint32_t latency_frames = 0;
   atomic<uint32_t> current_latency_frames{ 0 };
-  atomic<float> panning{ 0 };
+  atomic<uint32_t> total_output_latency_frames { 0 };
   unique_ptr<cubeb_resampler, decltype(&cubeb_resampler_destroy)> resampler;
   /* This is true if a device change callback is currently running.  */
   atomic<bool> switching_device{ false };
   atomic<bool> buffer_size_change_state{ false };
   AudioDeviceID aggregate_device_id = kAudioObjectUnknown;  // the aggregate device id
   AudioObjectID plugin_id = kAudioObjectUnknown;            // used to create aggregate device
   /* Mixer interface */
   unique_ptr<cubeb_mixer, decltype(&cubeb_mixer_destroy)> mixer;
@@ -363,34 +362,35 @@ cubeb_channel_to_channel_label(cubeb_cha
 }
 
 #if TARGET_OS_IPHONE
 typedef UInt32 AudioDeviceID;
 typedef UInt32 AudioObjectID;
 
 #define AudioGetCurrentHostTime mach_absolute_time
 
+#endif
+
 uint64_t
-AudioConvertHostTimeToNanos(uint64_t host_time)
+ConvertHostTimeToNanos(uint64_t host_time)
 {
   static struct mach_timebase_info timebase_info;
   static bool initialized = false;
   if (!initialized) {
     mach_timebase_info(&timebase_info);
     initialized = true;
   }
 
   long double answer = host_time;
   if (timebase_info.numer != timebase_info.denom) {
     answer *= timebase_info.numer;
     answer /= timebase_info.denom;
   }
   return (uint64_t)answer;
 }
-#endif
 
 static void
 audiounit_increment_active_streams(cubeb * ctx)
 {
   ctx->mutex.assert_current_thread_owns();
   ctx->active_streams += 1;
 }
 
@@ -578,16 +578,25 @@ audiounit_output_callback(void * user_pt
                           UInt32 output_frames,
                           AudioBufferList * outBufferList)
 {
   assert(AU_OUT_BUS == bus);
   assert(outBufferList->mNumberBuffers == 1);
 
   cubeb_stream * stm = static_cast<cubeb_stream *>(user_ptr);
 
+  uint64_t now = ConvertHostTimeToNanos(mach_absolute_time());
+  uint64_t audio_output_time = ConvertHostTimeToNanos(tstamp->mHostTime);
+  uint64_t output_latency_ns = audio_output_time - now;
+
+  const int ns2s = 1e9;
+  // The total output latency is the timestamp difference + the stream latency +
+  // the hardware latency.
+  stm->total_output_latency_frames = output_latency_ns * stm->output_hw_rate / ns2s + stm->current_latency_frames;
+
   ALOGV("(%p) output: buffers %u, size %u, channels %u, frames %u, total input frames %lu.",
         stm,
         (unsigned int) outBufferList->mNumberBuffers,
         (unsigned int) outBufferList->mBuffers[0].mDataByteSize,
         (unsigned int) outBufferList->mBuffers[0].mNumberChannels,
         (unsigned int) output_frames,
         has_input(stm) ? stm->input_linear_buffer->length() / stm->input_desc.mChannelsPerFrame : 0);
 
@@ -676,45 +685,31 @@ audiounit_output_callback(void * user_pt
     audiounit_make_silent(&outBufferList->mBuffers[0]);
     return noErr;
   }
 
   stm->draining = (UInt32) outframes < output_frames;
   stm->frames_played = stm->frames_queued;
   stm->frames_queued += outframes;
 
-  AudioFormatFlags outaff = stm->output_desc.mFormatFlags;
-  float panning = (stm->output_desc.mChannelsPerFrame == 2) ?
-      stm->panning.load(memory_order_relaxed) : 0.0f;
-
   /* Post process output samples. */
   if (stm->draining) {
     size_t outbpf = cubeb_sample_size(stm->output_stream_params.format);
     /* Clear missing frames (silence) */
     memset((uint8_t*)output_buffer + outframes * outbpf, 0, (output_frames - outframes) * outbpf);
   }
 
   /* Mixing */
   if (stm->mixer) {
     audiounit_mix_output_buffer(stm,
                                 output_frames,
                                 output_buffer,
                                 stm->temp_buffer_size,
                                 outBufferList->mBuffers[0].mData,
                                 outBufferList->mBuffers[0].mDataByteSize);
-  } else {
-    /* Pan stereo. */
-    if (panning != 0.0f) {
-      if (outaff & kAudioFormatFlagIsFloat) {
-        cubeb_pan_stereo_buffer_float(
-          (float*)output_buffer, outframes, panning);
-      } else if (outaff & kAudioFormatFlagIsSignedInteger) {
-        cubeb_pan_stereo_buffer_int((short*)output_buffer, outframes, panning);
-      }
-    }
   }
 
   return noErr;
 }
 
 extern "C" {
 int
 audiounit_init(cubeb ** context, char const * /* context_name */)
@@ -2968,17 +2963,17 @@ audiounit_stream_get_position(cubeb_stre
 
 int
 audiounit_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
 {
 #if TARGET_OS_IPHONE
   //TODO
   return CUBEB_ERROR_NOT_SUPPORTED;
 #else
-  *latency = stm->current_latency_frames;
+  *latency = stm->total_output_latency_frames;
   return CUBEB_OK;
 #endif
 }
 
 static int
 audiounit_stream_get_volume(cubeb_stream * stm, float * volume)
 {
   assert(stm->output_unit);
@@ -3005,26 +3000,16 @@ audiounit_stream_set_volume(cubeb_stream
 
   if (r != noErr) {
     LOG("AudioUnitSetParameter/kHALOutputParam_Volume rv=%d", r);
     return CUBEB_ERROR;
   }
   return CUBEB_OK;
 }
 
-int audiounit_stream_set_panning(cubeb_stream * stm, float panning)
-{
-  if (stm->output_desc.mChannelsPerFrame > 2) {
-    return CUBEB_ERROR_INVALID_PARAMETER;
-  }
-
-  stm->panning.store(panning, memory_order_relaxed);
-  return CUBEB_OK;
-}
-
 unique_ptr<char[]> convert_uint32_into_string(UInt32 data)
 {
   // Simply create an empty string if no data.
   size_t size = data == 0 ? 0 : 4; // 4 bytes for uint32.
   auto str = unique_ptr<char[]> { new char[size + 1] }; // + 1 for '\0'.
   str[size] = '\0';
   if (size < 4) {
     return str;
@@ -3616,14 +3601,13 @@ cubeb_ops const audiounit_ops = {
   /*.stream_init =*/ audiounit_stream_init,
   /*.stream_destroy =*/ audiounit_stream_destroy,
   /*.stream_start =*/ audiounit_stream_start,
   /*.stream_stop =*/ audiounit_stream_stop,
   /*.stream_reset_default_device =*/ nullptr,
   /*.stream_get_position =*/ audiounit_stream_get_position,
   /*.stream_get_latency =*/ audiounit_stream_get_latency,
   /*.stream_set_volume =*/ audiounit_stream_set_volume,
-  /*.stream_set_panning =*/ audiounit_stream_set_panning,
   /*.stream_get_current_device =*/ audiounit_stream_get_current_device,
   /*.stream_device_destroy =*/ audiounit_stream_device_destroy,
   /*.stream_register_device_changed_callback =*/ audiounit_stream_register_device_changed_callback,
   /*.register_device_collection_changed =*/ audiounit_register_device_collection_changed
 };
--- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_jack.cpp
+++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_jack.cpp
@@ -125,17 +125,16 @@ static struct cubeb_ops const cbjack_ops
   .stream_init = cbjack_stream_init,
   .stream_destroy = cbjack_stream_destroy,
   .stream_start = cbjack_stream_start,
   .stream_stop = cbjack_stream_stop,
   .stream_reset_default_device = NULL,
   .stream_get_position = cbjack_stream_get_position,
   .stream_get_latency = cbjack_get_latency,
   .stream_set_volume = cbjack_stream_set_volume,
-  .stream_set_panning = NULL,
   .stream_get_current_device = cbjack_stream_get_current_device,
   .stream_device_destroy = cbjack_stream_device_destroy,
   .stream_register_device_changed_callback = NULL,
   .register_device_collection_changed = NULL
 };
 
 struct cubeb_stream {
   /* Note: Must match cubeb_stream layout in cubeb.c. */
--- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_kai.c
+++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_kai.c
@@ -357,14 +357,13 @@ static struct cubeb_ops const kai_ops = 
   /*.stream_init =*/ kai_stream_init,
   /*.stream_destroy =*/ kai_stream_destroy,
   /*.stream_start =*/ kai_stream_start,
   /*.stream_stop =*/ kai_stream_stop,
   /*.stream_reset_default_device =*/ NULL,
   /*.stream_get_position =*/ kai_stream_get_position,
   /*.stream_get_latency = */ kai_stream_get_latency,
   /*.stream_set_volume =*/ kai_stream_set_volume,
-  /*.stream_set_panning =*/ NULL,
   /*.stream_get_current_device =*/ NULL,
   /*.stream_device_destroy =*/ NULL,
   /*.stream_register_device_changed_callback=*/ NULL,
   /*.register_device_collection_changed=*/ NULL
 };
--- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_opensl.c
+++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_opensl.c
@@ -1668,14 +1668,13 @@ static struct cubeb_ops const opensl_ops
   .stream_init = opensl_stream_init,
   .stream_destroy = opensl_stream_destroy,
   .stream_start = opensl_stream_start,
   .stream_stop = opensl_stream_stop,
   .stream_reset_default_device = NULL,
   .stream_get_position = opensl_stream_get_position,
   .stream_get_latency = NULL,
   .stream_set_volume = opensl_stream_set_volume,
-  .stream_set_panning = NULL,
   .stream_get_current_device = NULL,
   .stream_device_destroy = NULL,
   .stream_register_device_changed_callback = NULL,
   .register_device_collection_changed = NULL
 };
deleted file mode 100644
--- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_panner.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright © 2014 Mozilla Foundation
- *
- * This program is made available under an ISC-style license.  See the
- * accompanying file LICENSE for details.
- */
-
-#define _USE_MATH_DEFINES
-#include <math.h>
-#include <stdint.h>
-
-#include "cubeb_panner.h"
-
-#ifndef M_PI
-#define M_PI 3.14159263
-#endif
-
-/**
- * We use a cos/sin law.
- */
-
-namespace {
-template<typename T>
-void cubeb_pan_stereo_buffer(T * buf, uint32_t frames, float pan)
-{
-  if (pan == 0.0) {
-    return;
-  }
-  /* rescale in [0; 1] */
-  pan += 1;
-  pan /= 2;
-  float left_gain  = float(cos(pan * M_PI * 0.5));
-  float right_gain = float(sin(pan * M_PI * 0.5));
-
-  /* In we are panning on the left, pan the right channel into the left one and
-   * vice-versa. */
-  if (pan < 0.5) {
-    for (uint32_t i = 0; i < frames * 2; i+=2) {
-      buf[i]     = T(buf[i] + buf[i + 1] * left_gain);
-      buf[i + 1] = T(buf[i + 1] * right_gain);
-    }
-  } else {
-    for (uint32_t i = 0; i < frames * 2; i+=2) {
-      buf[i]     = T(buf[i] * left_gain);
-      buf[i + 1] = T(buf[i + 1] + buf[i] * right_gain);
-    }
-  }
-}
-}
-
-void cubeb_pan_stereo_buffer_float(float * buf, uint32_t frames, float pan)
-{
-  cubeb_pan_stereo_buffer(buf, frames, pan);
-}
-
-void cubeb_pan_stereo_buffer_int(short * buf, uint32_t frames, float pan)
-{
-  cubeb_pan_stereo_buffer(buf, frames, pan);
-}
-
deleted file mode 100644
--- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_panner.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright © 2014 Mozilla Foundation
- *
- * This program is made available under an ISC-style license.  See the
- * accompanying file LICENSE for details.
- */
-
-#if !defined(CUBEB_PANNER)
-#define CUBEB_PANNER
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-/**
- * Pan an integer or an float stereo buffer according to a cos/sin pan law
- * @param buf the buffer to pan
- * @param frames the number of frames in `buf`
- * @param pan a float in [-1.0; 1.0]
- */
-void cubeb_pan_stereo_buffer_float(float * buf, uint32_t frames, float pan);
-void cubeb_pan_stereo_buffer_int(short* buf, uint32_t frames, float pan);
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif
--- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_pulse.c
+++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_pulse.c
@@ -568,17 +568,19 @@ layout_to_channel_map(cubeb_channel_layo
   for (uint32_t i = 0 ; channelMap != 0; ++i) {
     uint32_t channel = (channelMap & 1) << i;
     if (channel != 0) {
       cm->map[channels] = cubeb_channel_to_pa_channel(channel);
       channels++;
     }
     channelMap = channelMap >> 1;
   }
-  cm->channels = cubeb_channel_layout_nb_channels(layout);
+  unsigned int channels_from_layout = cubeb_channel_layout_nb_channels(layout);
+  assert(channels_from_layout <= UINT8_MAX);
+  cm->channels = (uint8_t) channels_from_layout;
 }
 
 static void pulse_context_destroy(cubeb * ctx);
 static void pulse_destroy(cubeb * ctx);
 
 static int
 pulse_context_init(cubeb * ctx)
 {
@@ -821,17 +823,19 @@ create_pa_stream(cubeb_stream * stm,
     return CUBEB_ERROR_NOT_SUPPORTED;
   }
   *pa_stm = NULL;
   pa_sample_spec ss;
   ss.format = to_pulse_format(stream_params->format);
   if (ss.format == PA_SAMPLE_INVALID)
     return CUBEB_ERROR_INVALID_FORMAT;
   ss.rate = stream_params->rate;
-  ss.channels = stream_params->channels;
+  if (stream_params->channels > UINT8_MAX)
+    return CUBEB_ERROR_INVALID_FORMAT;
+  ss.channels = (uint8_t) stream_params->channels;
 
   if (stream_params->layout == CUBEB_LAYOUT_UNDEFINED) {
     pa_channel_map cm;
     if (stream_params->channels <= 8 &&
        !WRAP(pa_channel_map_init_auto)(&cm, stream_params->channels, PA_CHANNEL_MAP_DEFAULT)) {
       LOG("Layout undefined and PulseAudio's default layout has not been configured, guess one.");
       layout_to_channel_map(pulse_default_layout_for_channels(stream_params->channels), &cm);
       *pa_stm = WRAP(pa_stream_new)(stm->context->context, stream_name, &ss, &cm);
@@ -1175,63 +1179,16 @@ sink_input_info_cb(pa_context * c, pa_si
 {
   struct sink_input_info_result * r = u;
   if (!eol) {
     *r->cvol = i->volume;
   }
   WRAP(pa_threaded_mainloop_signal)(r->mainloop, 0);
 }
 
-static int
-pulse_stream_set_panning(cubeb_stream * stm, float panning)
-{
-  const pa_channel_map * map;
-  pa_cvolume cvol;
-  uint32_t index;
-  pa_operation * op;
-
-  if (!stm->output_stream) {
-    return CUBEB_ERROR;
-  }
-
-  WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
-
-  map = WRAP(pa_stream_get_channel_map)(stm->output_stream);
-  if (!WRAP(pa_channel_map_can_balance)(map)) {
-    WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
-    return CUBEB_ERROR;
-  }
-
-  index = WRAP(pa_stream_get_index)(stm->output_stream);
-
-  struct sink_input_info_result r = { &cvol, stm->context->mainloop };
-  op = WRAP(pa_context_get_sink_input_info)(stm->context->context,
-                                            index,
-                                            sink_input_info_cb,
-                                            &r);
-  if (op) {
-    operation_wait(stm->context, stm->output_stream, op);
-    WRAP(pa_operation_unref)(op);
-  }
-
-  WRAP(pa_cvolume_set_balance)(&cvol, map, panning);
-
-  op = WRAP(pa_context_set_sink_input_volume)(stm->context->context,
-                                              index, &cvol, volume_success,
-                                              stm);
-  if (op) {
-    operation_wait(stm->context, stm->output_stream, op);
-    WRAP(pa_operation_unref)(op);
-  }
-
-  WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
-
-  return CUBEB_OK;
-}
-
 typedef struct {
   char * default_sink_name;
   char * default_source_name;
 
   cubeb_device_info * devinfo;
   uint32_t max;
   uint32_t count;
   cubeb * context;
@@ -1628,14 +1585,13 @@ static struct cubeb_ops const pulse_ops 
   .stream_init = pulse_stream_init,
   .stream_destroy = pulse_stream_destroy,
   .stream_start = pulse_stream_start,
   .stream_stop = pulse_stream_stop,
   .stream_reset_default_device = NULL,
   .stream_get_position = pulse_stream_get_position,
   .stream_get_latency = pulse_stream_get_latency,
   .stream_set_volume = pulse_stream_set_volume,
-  .stream_set_panning = pulse_stream_set_panning,
   .stream_get_current_device = pulse_stream_get_current_device,
   .stream_device_destroy = pulse_stream_device_destroy,
   .stream_register_device_changed_callback = NULL,
   .register_device_collection_changed = pulse_register_device_collection_changed
 };
--- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_sndio.c
+++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_sndio.c
@@ -567,14 +567,13 @@ static struct cubeb_ops const sndio_ops 
   .stream_init = sndio_stream_init,
   .stream_destroy = sndio_stream_destroy,
   .stream_start = sndio_stream_start,
   .stream_stop = sndio_stream_stop,
   .stream_reset_default_device = NULL,
   .stream_get_position = sndio_stream_get_position,
   .stream_get_latency = sndio_stream_get_latency,
   .stream_set_volume = sndio_stream_set_volume,
-  .stream_set_panning = NULL,
   .stream_get_current_device = NULL,
   .stream_device_destroy = NULL,
   .stream_register_device_changed_callback = NULL,
   .register_device_collection_changed = NULL
 };
--- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_sun.c
+++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_sun.c
@@ -740,14 +740,13 @@ static struct cubeb_ops const sun_ops = 
   .stream_init = sun_stream_init,
   .stream_destroy = sun_stream_destroy,
   .stream_start = sun_stream_start,
   .stream_stop = sun_stream_stop,
   .stream_reset_default_device = NULL,
   .stream_get_position = sun_stream_get_position,
   .stream_get_latency = sun_stream_get_latency,
   .stream_set_volume = sun_stream_set_volume,
-  .stream_set_panning = NULL,
   .stream_get_current_device = sun_get_current_device,
   .stream_device_destroy = sun_stream_device_destroy,
   .stream_register_device_changed_callback = NULL,
   .register_device_collection_changed = NULL
 };
--- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_wasapi.cpp
+++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_wasapi.cpp
@@ -28,16 +28,64 @@
 
 #include "cubeb/cubeb.h"
 #include "cubeb-internal.h"
 #include "cubeb_mixer.h"
 #include "cubeb_resampler.h"
 #include "cubeb_strings.h"
 #include "cubeb_utils.h"
 
+// Windows 10 exposes the IAudioClient3 interface to create low-latency streams.
+// Copy the interface definition from audioclient.h here to make the code simpler
+// and so that we can still access IAudioClient3 via COM if cubeb was compiled
+// against an older SDK.
+#ifndef __IAudioClient3_INTERFACE_DEFINED__
+#define __IAudioClient3_INTERFACE_DEFINED__
+MIDL_INTERFACE("7ED4EE07-8E67-4CD4-8C1A-2B7A5987AD42")
+IAudioClient3 : public IAudioClient
+{
+public:
+    virtual HRESULT STDMETHODCALLTYPE GetSharedModeEnginePeriod(
+        /* [annotation][in] */
+        _In_  const WAVEFORMATEX *pFormat,
+        /* [annotation][out] */
+        _Out_  UINT32 *pDefaultPeriodInFrames,
+        /* [annotation][out] */
+        _Out_  UINT32 *pFundamentalPeriodInFrames,
+        /* [annotation][out] */
+        _Out_  UINT32 *pMinPeriodInFrames,
+        /* [annotation][out] */
+        _Out_  UINT32 *pMaxPeriodInFrames) = 0;
+
+    virtual HRESULT STDMETHODCALLTYPE GetCurrentSharedModeEnginePeriod(
+        /* [unique][annotation][out] */
+        _Out_  WAVEFORMATEX **ppFormat,
+        /* [annotation][out] */
+        _Out_  UINT32 *pCurrentPeriodInFrames) = 0;
+
+    virtual HRESULT STDMETHODCALLTYPE InitializeSharedAudioStream(
+        /* [annotation][in] */
+        _In_  DWORD StreamFlags,
+        /* [annotation][in] */
+        _In_  UINT32 PeriodInFrames,
+        /* [annotation][in] */
+        _In_  const WAVEFORMATEX *pFormat,
+        /* [annotation][in] */
+        _In_opt_  LPCGUID AudioSessionGuid) = 0;
+};
+#ifdef __CRT_UUID_DECL
+// Required for MinGW
+__CRT_UUID_DECL(IAudioClient3, 0x7ED4EE07, 0x8E67, 0x4CD4, 0x8C, 0x1A, 0x2B, 0x7A, 0x59, 0x87, 0xAD, 0x42)
+#endif
+#endif
+// Copied from audioclient.h in the Windows 10 SDK
+#ifndef AUDCLNT_E_ENGINE_PERIODICITY_LOCKED
+#define AUDCLNT_E_ENGINE_PERIODICITY_LOCKED    AUDCLNT_ERR(0x028)
+#endif
+
 #ifndef PKEY_Device_FriendlyName
 DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName,    0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);    // DEVPROP_TYPE_STRING
 #endif
 #ifndef PKEY_Device_InstanceId
 DEFINE_PROPERTYKEY(PKEY_Device_InstanceId,      0x78c34fc8, 0x104a, 0x4aca, 0x9e, 0xa4, 0x52, 0x4d, 0x52, 0x99, 0x6e, 0x57, 0x00000100); //    VT_LPWSTR
 #endif
 
 namespace {
@@ -687,17 +735,17 @@ get_rate(cubeb_stream * stm)
 {
   return has_input(stm) ? stm->input_stream_params.rate
                         : stm->output_stream_params.rate;
 }
 
 uint32_t
 hns_to_frames(uint32_t rate, REFERENCE_TIME hns)
 {
-  return std::ceil(hns / 10000000.0 * rate);
+  return std::ceil((hns - 1) / 10000000.0 * rate);
 }
 
 uint32_t
 hns_to_frames(cubeb_stream * stm, REFERENCE_TIME hns)
 {
   return hns_to_frames(get_rate(stm), hns);
 }
 
@@ -1595,31 +1643,36 @@ wasapi_get_min_latency(cubeb * ctx, cube
   hr = device->Activate(__uuidof(IAudioClient),
                         CLSCTX_INPROC_SERVER,
                         NULL, client.receive_vpp());
   if (FAILED(hr)) {
     LOG("Could not activate device for latency: %lx", hr);
     return CUBEB_ERROR;
   }
 
-  /* The second parameter is for exclusive mode, that we don't use. */
+  REFERENCE_TIME minimum_period;
   REFERENCE_TIME default_period;
-  hr = client->GetDevicePeriod(&default_period, NULL);
+  hr = client->GetDevicePeriod(&default_period, &minimum_period);
   if (FAILED(hr)) {
     LOG("Could not get device period: %lx", hr);
     return CUBEB_ERROR;
   }
 
-  LOG("default device period: %I64d", default_period);
-
-  /* According to the docs, the best latency we can achieve is by synchronizing
-     the stream and the engine.
+  LOG("default device period: %I64d, minimum device period: %I64d", default_period, minimum_period);
+
+  /* If we're on Windows 10, we can use IAudioClient3 to get minimal latency.
+     Otherwise, according to the docs, the best latency we can achieve is by
+     synchronizing the stream and the engine.
      http://msdn.microsoft.com/en-us/library/windows/desktop/dd370871%28v=vs.85%29.aspx */
 
-  *latency_frames = hns_to_frames(params.rate, default_period);
+  #ifdef _WIN32_WINNT_WIN10
+    *latency_frames = hns_to_frames(params.rate, minimum_period);
+  #else
+    *latency_frames = hns_to_frames(params.rate, default_period);
+  #endif
 
   LOG("Minimum latency in frames: %u", *latency_frames);
 
   return CUBEB_OK;
 }
 
 int
 wasapi_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
@@ -1715,16 +1768,119 @@ handle_channel_layout(cubeb_stream * stm
     *reinterpret_cast<WAVEFORMATEXTENSIBLE *>(mix_format.get()) = hw_mix_format;
   } else if (hr == S_OK) {
     LOG("Requested format accepted by WASAPI.");
   } else {
     LOG("IsFormatSupported unhandled error: %lx", hr);
   }
 }
 
+static bool
+initialize_iaudioclient3(com_ptr<IAudioClient> & audio_client,
+                         cubeb_stream * stm,
+                         const com_heap_ptr<WAVEFORMATEX> & mix_format,
+                         DWORD flags,
+                         EDataFlow direction)
+{
+  com_ptr<IAudioClient3> audio_client3;
+  audio_client->QueryInterface<IAudioClient3>(audio_client3.receive());
+  if (!audio_client3) {
+    LOG("Could not get IAudioClient3 interface");
+    return false;
+  }
+
+  if (flags & AUDCLNT_STREAMFLAGS_LOOPBACK) {
+    // IAudioClient3 doesn't work with loopback streams, and will return error
+    // 88890021: AUDCLNT_E_INVALID_STREAM_FLAG
+    LOG("Audio stream is loopback, not using IAudioClient3");
+    return false;
+  }
+
+  // IAudioClient3 doesn't support AUDCLNT_STREAMFLAGS_NOPERSIST, and will return
+  // AUDCLNT_E_INVALID_STREAM_FLAG. This is undocumented.
+  flags = flags ^ AUDCLNT_STREAMFLAGS_NOPERSIST;
+
+  // Some people have reported glitches with capture streams:
+  // http://blog.nirbheek.in/2018/03/low-latency-audio-on-windows-with.html
+  if (direction == eCapture) {
+    LOG("Audio stream is capture, not using IAudioClient3");
+    return false;
+  }
+
+  // Possibly initialize a shared-mode stream using IAudioClient3. Initializing
+  // a stream this way lets you request lower latencies, but also locks the global
+  // WASAPI engine at that latency.
+  // - If we request a shared-mode stream, streams created with IAudioClient will
+  //   have their latency adjusted to match. When  the shared-mode stream is
+  //   closed, they'll go back to normal.
+  // - If there's already a shared-mode stream running, then we cannot request
+  //   the engine change to a different latency - we have to match it.
+  // - It's antisocial to lock the WASAPI engine at its default latency. If we
+  //   would do this, then stop and use IAudioClient instead.
+
+  HRESULT hr;
+  uint32_t default_period = 0, fundamental_period = 0, min_period = 0, max_period = 0;
+  hr = audio_client3->GetSharedModeEnginePeriod(mix_format.get(), &default_period, &fundamental_period, &min_period, &max_period);
+  if (FAILED(hr)) {
+    LOG("Could not get shared mode engine period: error: %lx", hr);
+    return false;
+  }
+  uint32_t requested_latency = stm->latency;
+  if (requested_latency >= default_period) {
+    LOG("Requested latency %i greater than default latency %i, not using IAudioClient3", requested_latency, default_period);
+    return false;
+  }
+  LOG("Got shared mode engine period: default=%i fundamental=%i min=%i max=%i", default_period, fundamental_period, min_period, max_period);
+  // Snap requested latency to a valid value
+  uint32_t old_requested_latency = requested_latency;
+  if (requested_latency < min_period) {
+    requested_latency = min_period;
+  }
+  requested_latency -= (requested_latency - min_period) % fundamental_period;
+  if (requested_latency != old_requested_latency) {
+    LOG("Requested latency %i was adjusted to %i", old_requested_latency, requested_latency);
+  }
+
+  hr = audio_client3->InitializeSharedAudioStream(flags, requested_latency, mix_format.get(), NULL);
+  if (SUCCEEDED(hr)) {
+    return true;
+  }
+  else if (hr == AUDCLNT_E_ENGINE_PERIODICITY_LOCKED) {
+    LOG("Got AUDCLNT_E_ENGINE_PERIODICITY_LOCKED, adjusting latency request");
+  } else {
+    LOG("Could not initialize shared stream with IAudioClient3: error: %lx", hr);
+    return false;
+  }
+
+  uint32_t current_period = 0;
+  WAVEFORMATEX* current_format = nullptr;
+  // We have to pass a valid WAVEFORMATEX** and not nullptr, otherwise
+  // GetCurrentSharedModeEnginePeriod will return E_POINTER
+  hr = audio_client3->GetCurrentSharedModeEnginePeriod(&current_format, &current_period);
+  CoTaskMemFree(current_format);
+  if (FAILED(hr)) {
+    LOG("Could not get current shared mode engine period: error: %lx", hr);
+    return false;
+  }
+
+  if (current_period >= default_period) {
+    LOG("Current shared mode engine period %i too high, not using IAudioClient", current_period);
+    return false;
+  }
+
+  hr = audio_client3->InitializeSharedAudioStream(flags, current_period, mix_format.get(), NULL);
+  if (SUCCEEDED(hr)) {
+    LOG("Current shared mode engine period is %i instead of requested %i", current_period, requested_latency);
+    return true;
+  }
+
+  LOG("Could not initialize shared stream with IAudioClient3: error: %lx", hr);
+  return false;
+}
+
 #define DIRECTION_NAME (direction == eCapture ? "capture" : "render")
 
 template<typename T>
 int setup_wasapi_stream_one_side(cubeb_stream * stm,
                                  cubeb_stream_params * stream_params,
                                  wchar_t const * devid,
                                  EDataFlow direction,
                                  REFIID riid,
@@ -1765,19 +1921,25 @@ int setup_wasapi_stream_one_side(cubeb_s
           LOG("Could not get default %s endpoint, error: %lx\n", DIRECTION_NAME, hr);
         }
         return CUBEB_ERROR;
       }
     }
 
     /* Get a client. We will get all other interfaces we need from
      * this pointer. */
-    hr = device->Activate(__uuidof(IAudioClient),
+    hr = device->Activate(__uuidof(IAudioClient3),
                           CLSCTX_INPROC_SERVER,
                           NULL, audio_client.receive_vpp());
+    if (hr == E_NOINTERFACE) {
+      hr = device->Activate(__uuidof(IAudioClient),
+                            CLSCTX_INPROC_SERVER,
+                            NULL, audio_client.receive_vpp());
+    }
+
     if (FAILED(hr)) {
       LOG("Could not activate the device to get an audio"
           " client for %s: error: %lx\n", DIRECTION_NAME, hr);
       // A particular device can't be activated because it has been
       // unplugged, try fall back to the default audio device.
       if (devid && hr == AUDCLNT_E_DEVICE_INVALIDATED) {
         LOG("Trying again with the default %s audio device.", DIRECTION_NAME);
         devid = nullptr;
@@ -1832,22 +1994,26 @@ int setup_wasapi_stream_one_side(cubeb_s
   // Check if a loopback device should be requested. Note that event callbacks
   // do not work with loopback devices, so only request these if not looping.
   if (is_loopback) {
     flags |= AUDCLNT_STREAMFLAGS_LOOPBACK;
   } else {
     flags |= AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
   }
 
-  hr = audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED,
-                                flags,
-                                frames_to_hns(stm, stm->latency),
-                                0,
-                                mix_format.get(),
-                                NULL);
+  if (initialize_iaudioclient3(audio_client, stm, mix_format, flags, direction)) {
+    LOG("Initialized with IAudioClient3");
+  } else {
+    hr = audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED,
+                                  flags,
+                                  frames_to_hns(stm, stm->latency),
+                                  0,
+                                  mix_format.get(),
+                                  NULL);
+  }
   if (FAILED(hr)) {
     LOG("Unable to initialize audio client for %s: %lx.", DIRECTION_NAME, hr);
     return CUBEB_ERROR;
   }
 
   hr = audio_client->GetBufferSize(buffer_frame_count);
   if (FAILED(hr)) {
     LOG("Could not get the buffer size from the client"
@@ -2780,15 +2946,14 @@ cubeb_ops const wasapi_ops = {
   /*.stream_init =*/ wasapi_stream_init,
   /*.stream_destroy =*/ wasapi_stream_destroy,
   /*.stream_start =*/ wasapi_stream_start,
   /*.stream_stop =*/ wasapi_stream_stop,
   /*.stream_reset_default_device =*/ wasapi_stream_reset_default_device,
   /*.stream_get_position =*/ wasapi_stream_get_position,
   /*.stream_get_latency =*/ wasapi_stream_get_latency,
   /*.stream_set_volume =*/ wasapi_stream_set_volume,
-  /*.stream_set_panning =*/ NULL,
   /*.stream_get_current_device =*/ NULL,
   /*.stream_device_destroy =*/ NULL,
   /*.stream_register_device_changed_callback =*/ NULL,
   /*.register_device_collection_changed =*/ wasapi_register_device_collection_changed,
 };
 } // namespace anonymous
--- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_winmm.c
+++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_winmm.c
@@ -1055,14 +1055,13 @@ static struct cubeb_ops const winmm_ops 
   /*.stream_init =*/ winmm_stream_init,
   /*.stream_destroy =*/ winmm_stream_destroy,
   /*.stream_start =*/ winmm_stream_start,
   /*.stream_stop =*/ winmm_stream_stop,
   /*.stream_reset_default_device =*/ NULL,
   /*.stream_get_position =*/ winmm_stream_get_position,
   /*.stream_get_latency = */ winmm_stream_get_latency,
   /*.stream_set_volume =*/ winmm_stream_set_volume,
-  /*.stream_set_panning =*/ NULL,
   /*.stream_get_current_device =*/ NULL,
   /*.stream_device_destroy =*/ NULL,
   /*.stream_register_device_changed_callback=*/ NULL,
   /*.register_device_collection_changed =*/ NULL
 };
--- a/third_party/rust/cubeb-sys/libcubeb/test/test_audio.cpp
+++ b/third_party/rust/cubeb-sys/libcubeb/test/test_audio.cpp
@@ -143,17 +143,17 @@ int run_test(int num_channels, int sampl
 
   cubeb_stream_start(stream);
   delay(200);
   cubeb_stream_stop(stream);
 
   return r;
 }
 
-int run_panning_volume_test(int is_float)
+int run_volume_test(int is_float)
 {
   int r = CUBEB_OK;
 
   cubeb *ctx = NULL;
 
   r = common_init(&ctx, "Cubeb audio test");
   if (r != CUBEB_OK) {
     fprintf(stderr, "Error initializing cubeb library\n");
@@ -198,39 +198,27 @@ int run_panning_volume_test(int is_float
 
     cubeb_stream_set_volume(stream, i/4.0f);
     cubeb_stream_start(stream);
     delay(400);
     cubeb_stream_stop(stream);
     delay(100);
   }
 
-  fprintf(stderr, "Testing: panning\n");
-  for(int i=-4;i <= 4; ++i)
-  {
-    fprintf(stderr, "Panning: %.2f\n", i/4.0f);
-
-    cubeb_stream_set_panning(stream, i/4.0f);
-    cubeb_stream_start(stream);
-    delay(400);
-    cubeb_stream_stop(stream);
-    delay(100);
-  }
-
   return r;
 }
 
-TEST(cubeb, run_panning_volume_test_short)
+TEST(cubeb, run_volume_test_short)
 {
-  ASSERT_EQ(run_panning_volume_test(0), CUBEB_OK);
+  ASSERT_EQ(run_volume_test(0), CUBEB_OK);
 }
 
-TEST(cubeb, run_panning_volume_test_float)
+TEST(cubeb, run_volume_test_float)
 {
-  ASSERT_EQ(run_panning_volume_test(1), CUBEB_OK);
+  ASSERT_EQ(run_volume_test(1), CUBEB_OK);
 }
 
 TEST(cubeb, run_channel_rate_test)
 {
   unsigned int channel_values[] = {
     1,
     2,
     3,
--- a/third_party/rust/cubeb-sys/libcubeb/test/test_sanity.cpp
+++ b/third_party/rust/cubeb-sys/libcubeb/test/test_sanity.cpp
@@ -210,31 +210,28 @@ TEST(cubeb, configure_stream)
   cubeb_stream_params params;
 
   r = common_init(&ctx, "test_sanity");
   ASSERT_EQ(r, CUBEB_OK);
   ASSERT_NE(ctx, nullptr);
 
   params.format = STREAM_FORMAT;
   params.rate = STREAM_RATE;
-  params.channels = 2; // panning
+  params.channels = 2;
   params.layout = CUBEB_LAYOUT_STEREO;
   params.prefs = CUBEB_STREAM_PREF_NONE;
 
   r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, &params, STREAM_LATENCY,
                         test_data_callback, test_state_callback, &dummy);
   ASSERT_EQ(r, CUBEB_OK);
   ASSERT_NE(stream, nullptr);
 
   r = cubeb_stream_set_volume(stream, 1.0f);
   ASSERT_TRUE(r == 0 || r == CUBEB_ERROR_NOT_SUPPORTED);
 
-  r = cubeb_stream_set_panning(stream, 0.0f);
-  ASSERT_TRUE(r == 0 || r == CUBEB_ERROR_NOT_SUPPORTED);
-
   cubeb_stream_destroy(stream);
   cubeb_destroy(ctx);
 }
 
 TEST(cubeb, configure_stream_undefined_layout)
 {
   int r;
   cubeb * ctx;
@@ -242,17 +239,17 @@ TEST(cubeb, configure_stream_undefined_l
   cubeb_stream_params params;
 
   r = common_init(&ctx, "test_sanity");
   ASSERT_EQ(r, CUBEB_OK);
   ASSERT_NE(ctx, nullptr);
 
   params.format = STREAM_FORMAT;
   params.rate = STREAM_RATE;
-  params.channels = 2; // panning
+  params.channels = 2;
   params.layout = CUBEB_LAYOUT_UNDEFINED;
   params.prefs = CUBEB_STREAM_PREF_NONE;
 
   r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, &params, STREAM_LATENCY,
                         test_data_callback, test_state_callback, &dummy);
   ASSERT_EQ(r, CUBEB_OK);
   ASSERT_NE(stream, nullptr);
 
--- a/third_party/rust/cubeb-sys/libcubeb/tools/cubeb-test.cpp
+++ b/third_party/rust/cubeb-sys/libcubeb/tools/cubeb-test.cpp
@@ -12,17 +12,18 @@
 #endif
 
 #ifndef M_PI
 #define M_PI 3.14159263
 #endif
 
 // Default values if none specified
 #define DEFAULT_RATE 44100
-#define DEFAULT_CHANNELS 2
+#define DEFAULT_OUTPUT_CHANNELS 2
+#define DEFAULT_INPUT_CHANNELS 1
 
 static const char* state_to_string(cubeb_state state) {
   switch (state) {
     case CUBEB_STATE_STARTED:
       return "CUBEB_STATE_STARTED";
     case CUBEB_STATE_STOPPED:
       return "CUBEB_STATE_STOPPED";
     case CUBEB_STATE_DRAINED:
@@ -48,17 +49,20 @@ public:
 
   bool init(char const * backend_name = nullptr);
   bool init_stream();
   bool start_stream() const;
   bool stop_stream() const;
   bool destroy_stream() const;
   bool destroy();
   bool activate_log(cubeb_log_level log_level) const;
+  void set_latency_testing(bool on);
+  void set_latency_frames(uint32_t latency_frames);
   uint64_t get_stream_position() const;
+  uint32_t get_stream_latency() const;
 
   long user_data_cb(cubeb_stream* stm, void* user, const void* input_buffer,
                     void* output_buffer, long nframes);
 
   void user_state_cb(cubeb_stream* stm, void* user, cubeb_state state);
 
   bool register_device_collection_changed(cubeb_device_type devtype) const;
   bool unregister_device_collection_changed(cubeb_device_type devtype) const;
@@ -74,16 +78,19 @@ private:
 
   cubeb_stream* stream = nullptr;
   cubeb_devid output_device = nullptr;
   cubeb_devid input_device = nullptr;
 
   /* Accessed only from client and audio thread. */
   std::atomic<uint32_t> _rate = {0};
   std::atomic<uint32_t> _channels = {0};
+  std::atomic<bool> _latency_testing = {false};
+  std::atomic<uint32_t> _latency_frames = {0}; // if !0, override. Else, use min.
+
 
   /* Accessed only from audio thread. */
   uint32_t _total_frames = 0;
 };
 
 bool cubeb_client::init(char const * backend_name) {
   int rv = cubeb_init(&context, "Cubeb Test Application", nullptr);
   if (rv != CUBEB_OK) {
@@ -119,21 +126,37 @@ void io_device_changed_callback_s(cubeb*
 }
 
 bool cubeb_client::init_stream() {
   assert(has_input() || has_output());
 
   _rate = has_output() ? output_params.rate : input_params.rate;
   _channels = has_output() ? output_params.channels : input_params.channels;
 
-  int rv =
+  cubeb_stream_params params;
+  params.rate = _rate;
+  params.channels = 2;
+  params.format = CUBEB_SAMPLE_FLOAT32NE;
+
+  uint32_t latency = 0;
+  int rv = cubeb_get_min_latency(context, &params, &latency);
+  if (rv != CUBEB_OK) {
+    fprintf(stderr, "Could not get min latency.");
+    return false;
+  }
+
+  if (_latency_frames) {
+    latency = _latency_frames.load();
+    printf("Opening a stream with a forced latency of %d frames\n", latency);
+  }
+
+  rv =
       cubeb_stream_init(context, &stream, "Stream", input_device,
                         has_input() ? &input_params : nullptr, output_device,
-                        has_output() ? &output_params : nullptr, 512,
-                        user_data_cb_s, user_state_cb_s, this);
+                        has_output() ? &output_params : nullptr, latency, user_data_cb_s, user_state_cb_s, this);
   if (rv != CUBEB_OK) {
     fprintf(stderr, "Could not open the stream\n");
     return false;
   }
   return true;
 }
 
 bool cubeb_client::start_stream() const {
@@ -153,22 +176,32 @@ bool cubeb_client::stop_stream() const {
   }
   return true;
 }
 
 uint64_t cubeb_client::get_stream_position() const {
   uint64_t pos = 0;
   int rv = cubeb_stream_get_position(stream, &pos);
   if (rv != CUBEB_OK) {
-    fprintf(stderr, "Could not get the position the stream\n");
+    fprintf(stderr, "Could not get the position of the stream\n");
     return 0;
   }
   return pos;
 }
 
+uint32_t cubeb_client::get_stream_latency() const {
+  uint32_t latency = 0;
+  int rv = cubeb_stream_get_latency(stream, &latency);
+  if (rv != CUBEB_OK) {
+    fprintf(stderr, "Could not get the latency of the stream\n");
+    return 0;
+  }
+  return latency;
+}
+
 bool cubeb_client::destroy_stream() const {
   cubeb_stream_destroy(stream);
   return true;
 }
 
 bool cubeb_client::destroy() {
   cubeb_destroy(context);
   return true;
@@ -182,16 +215,24 @@ bool cubeb_client::activate_log(cubeb_lo
 
   if (cubeb_set_log_callback(log_level, log_callback) != CUBEB_OK) {
     fprintf(stderr, "Set log callback failed\n");
     return false;
   }
   return true;
 }
 
+void cubeb_client::set_latency_testing(bool on) {
+  _latency_testing = on;
+}
+
+void cubeb_client::set_latency_frames(uint32_t latency_frames) {
+  _latency_frames = latency_frames;
+}
+
 static void fill_with_sine_tone(float* buf, uint32_t num_of_frames,
                                uint32_t num_of_channels, uint32_t frame_rate,
                                uint32_t position) {
   for (uint32_t i = 0; i < num_of_frames; ++i) {
     for (uint32_t c = 0; c < num_of_channels; ++c) {
       buf[i * num_of_channels + c] =
           0.2 * sin(2 * M_PI * (i + position) * 350 / frame_rate);
       buf[i * num_of_channels + c] +=
@@ -201,17 +242,38 @@ static void fill_with_sine_tone(float* b
 }
 
 long cubeb_client::user_data_cb(cubeb_stream* stm, void* user,
                                 const void* input_buffer, void* output_buffer,
                                 long nframes) {
   if (input_buffer && output_buffer) {
     const float* in = static_cast<const float*>(input_buffer);
     float* out = static_cast<float*>(output_buffer);
-    memcpy(out, in, sizeof(float) * nframes * _channels);
+    if (_latency_testing) {
+      for (uint32_t i = 0; i < nframes; i++) {
+        // Impulses every second, mixed with the input signal fed back at half
+        // gain, to measure the input-to-output latency via feedback.
+        uint32_t clock = ((_total_frames + i) % _rate);
+        if (!clock) {
+          for (uint32_t j = 0; j < _channels; j++) {
+            out[i * _channels + j] = 1.0 + in[i] * 0.5;
+          }
+        } else {
+          for (uint32_t j = 0; j < _channels; j++) {
+            out[i * _channels + j] = 0.0 + in[i] * 0.5;
+          }
+        }
+      }
+    } else {
+      for (uint32_t i = 0; i < nframes; i++) {
+        for (uint32_t j = 0; j < _channels; j++) {
+          out[i * _channels + j] = in[i];
+        }
+      }
+    }
   } else if (output_buffer && !input_buffer) {
     fill_with_sine_tone(static_cast<float*>(output_buffer), nframes, _channels,
                        _rate, _total_frames);
   }
 
   _total_frames += nframes;
   return nframes;
 }
@@ -249,16 +311,17 @@ bool cubeb_client::unregister_device_col
   }
   return true;
 }
 
 enum play_mode {
   RECORD,
   PLAYBACK,
   DUPLEX,
+  LATENCY_TESTING,
   COLLECTION_CHANGE,
 };
 
 struct operation_data {
   play_mode pm;
   uint32_t rate;
   cubeb_device_type collection_device_type;
 };
@@ -277,24 +340,27 @@ void print_help() {
     "k: change device type to unknown\n"
     "r: register device collection changed callback for the current device type\n"
     "u: unregister device collection changed callback for the current device type\n"
     "q: quit\n"
     "h: print this message\n";
   fprintf(stderr, "%s\n", msg);
 }
 
-bool choose_action(const cubeb_client& cl, operation_data * op, char c) {
+bool choose_action(const cubeb_client& cl, operation_data * op, int c) {
+  // Consume "enter" and "space"
   while (c == 10 || c == 32) {
-    // Consume "enter and "space"
     c = getchar();
   }
+  if (c == EOF) {
+    c = 'q';
+  }
 
   if (c == 'q') {
-    if (op->pm == PLAYBACK || op->pm == RECORD || op->pm == DUPLEX) {
+    if (op->pm == PLAYBACK || op->pm == RECORD || op->pm == DUPLEX || op->pm == LATENCY_TESTING) {
       bool res = cl.stop_stream();
       if (!res) {
         fprintf(stderr, "stop_stream failed\n");
       }
       res = cl.destroy_stream();
       if (!res) {
         fprintf(stderr, "destroy_stream failed\n");
       }
@@ -329,17 +395,18 @@ bool choose_action(const cubeb_client& c
     bool res = cl.stop_stream();
     if (res) {
       fprintf(stderr, "stop_stream succeed\n");
     } else {
       fprintf(stderr, "stop_stream failed\n");
     }
   } else if (c == 'c') {
     uint64_t pos = cl.get_stream_position();
-    fprintf(stderr, "stream position %" PRIu64 "\n", pos);
+    uint64_t latency = cl.get_stream_latency();
+    fprintf(stderr, "stream position %" PRIu64 " (latency %" PRIu64 ")\n", pos, latency);
   } else if (c == 'i') {
     op->collection_device_type = CUBEB_DEVICE_TYPE_INPUT;
     fprintf(stderr, "collection device type changed to INPUT\n");
   } else if (c == 'o') {
     op->collection_device_type = CUBEB_DEVICE_TYPE_OUTPUT;
     fprintf(stderr, "collection device type changed to OUTPUT\n");
   } else if (c == 'a') {
     op->collection_device_type = static_cast<cubeb_device_type>(CUBEB_DEVICE_TYPE_INPUT | CUBEB_DEVICE_TYPE_OUTPUT);
@@ -357,17 +424,17 @@ bool choose_action(const cubeb_client& c
   } else if (c == 'u') {
     bool res = cl.unregister_device_collection_changed(op->collection_device_type);
     if (res) {
       fprintf(stderr, "unregister_device_collection_changed succeed\n");
     } else {
       fprintf(stderr, "unregister_device_collection_changed failed\n");
     }
   } else {
-    fprintf(stderr, "Error: %c is not a valid entry\n", c);
+    fprintf(stderr, "Error: '%c' is not a valid entry\n", c);
   }
 
   return true; // Loop up
 }
 
 int main(int argc, char* argv[]) {
 #ifdef _WIN32
   CoInitialize(nullptr);
@@ -377,22 +444,28 @@ int main(int argc, char* argv[]) {
   op.pm = PLAYBACK;
   if (argc > 1) {
     if ('r' == argv[1][0]) {
       op.pm = RECORD;
     } else if ('p' == argv[1][0]) {
       op.pm = PLAYBACK;
     } else if ('d' == argv[1][0]) {
       op.pm = DUPLEX;
+    } else if ('l' == argv[1][0]) {
+      op.pm = LATENCY_TESTING;
     } else if ('c' == argv[1][0]) {
       op.pm = COLLECTION_CHANGE;
     }
   }
   op.rate = DEFAULT_RATE;
-  if (argc > 2) {
+  uint32_t latency_override = 0;
+  if (op.pm == LATENCY_TESTING && argc > 2) {
+    latency_override = strtoul(argv[2], NULL, 10);
+    printf("LATENCY_TESTING %d\n", latency_override);
+  } else if (argc > 2) {
     op.rate = strtoul(argv[2], NULL, 0);
   }
 
   bool res = false;
   cubeb_client cl;
   cl.activate_log(CUBEB_LOG_DISABLED);
   fprintf(stderr, "Log level is DISABLED\n");
   cl.init();
@@ -404,23 +477,28 @@ int main(int argc, char* argv[]) {
     fprintf(stderr, "collection device type changed to OUTPUT\n");
     res = cl.register_device_collection_changed(op.collection_device_type);
     if (res) {
       fprintf(stderr, "register_device_collection_changed succeed\n");
     } else {
       fprintf(stderr, "register_device_collection_changed failed\n");
     }
   } else {
-    if (op.pm == PLAYBACK || op.pm == DUPLEX) {
-      cl.output_params = {CUBEB_SAMPLE_FLOAT32NE, op.rate, DEFAULT_CHANNELS,
-                          CUBEB_LAYOUT_UNDEFINED, CUBEB_STREAM_PREF_NONE};
+    if (op.pm == PLAYBACK || op.pm == DUPLEX || op.pm == LATENCY_TESTING) {
+      cl.output_params = {CUBEB_SAMPLE_FLOAT32NE, op.rate, DEFAULT_OUTPUT_CHANNELS,
+                          CUBEB_LAYOUT_STEREO, CUBEB_STREAM_PREF_NONE};
     }
-    if (op.pm == RECORD || op.pm == DUPLEX) {
-      cl.input_params = {CUBEB_SAMPLE_FLOAT32NE, op.rate, DEFAULT_CHANNELS,
-                         CUBEB_LAYOUT_UNDEFINED, CUBEB_STREAM_PREF_NONE};
+    if (op.pm == RECORD || op.pm == DUPLEX || op.pm == LATENCY_TESTING) {
+      cl.input_params = {CUBEB_SAMPLE_FLOAT32NE, op.rate, DEFAULT_INPUT_CHANNELS, CUBEB_LAYOUT_UNDEFINED, CUBEB_STREAM_PREF_NONE};
+    }
+    if (op.pm == LATENCY_TESTING) {
+      cl.set_latency_testing(true);
+      if (latency_override) {
+        cl.set_latency_frames(latency_override);
+      }
     }
     res = cl.init_stream();
     if (!res) {
       fprintf(stderr, "stream_init failed\n");
       return -1;
     }
     fprintf(stderr, "stream_init succeed\n");
 
--- a/third_party/rust/cubeb-sys/src/lib.rs
+++ b/third_party/rust/cubeb-sys/src/lib.rs
@@ -11,23 +11,21 @@ mod macros;
 mod callbacks;
 mod channel;
 mod context;
 mod device;
 mod error;
 mod format;
 mod log;
 mod mixer;
-mod panner;
 mod resampler;
 mod stream;
 
 pub use callbacks::*;
 pub use channel::*;
 pub use context::*;
 pub use device::*;
 pub use error::*;
 pub use format::*;
 pub use log::*;
 pub use mixer::*;
-pub use panner::*;
 pub use resampler::*;
 pub use stream::*;
deleted file mode 100644
--- a/third_party/rust/cubeb-sys/src/panner.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright © 2017-2018 Mozilla Foundation
-//
-// This program is made available under an ISC-style license.  See the
-// accompanying file LICENSE for details.
-
-use std::os::raw::{c_float, c_short};
-
-extern "C" {
-    pub fn cubeb_pan_stereo_buffer_float(buf: *mut c_float, frames: u32, pan: c_float);
-    pub fn cubeb_pan_stereo_buffer_int(buf: *mut c_short, frames: u32, pan: c_float);
-}
--- a/third_party/rust/cubeb-sys/src/stream.rs
+++ b/third_party/rust/cubeb-sys/src/stream.rs
@@ -62,17 +62,16 @@ impl fmt::Debug for cubeb_stream_params 
 extern "C" {
     pub fn cubeb_stream_destroy(stream: *mut cubeb_stream);
     pub fn cubeb_stream_start(stream: *mut cubeb_stream) -> c_int;
     pub fn cubeb_stream_stop(stream: *mut cubeb_stream) -> c_int;
     pub fn cubeb_stream_reset_default_device(stream: *mut cubeb_stream) -> c_int;
     pub fn cubeb_stream_get_position(stream: *mut cubeb_stream, position: *mut u64) -> c_int;
     pub fn cubeb_stream_get_latency(stream: *mut cubeb_stream, latency: *mut c_uint) -> c_int;
     pub fn cubeb_stream_set_volume(stream: *mut cubeb_stream, volume: c_float) -> c_int;
-    pub fn cubeb_stream_set_panning(stream: *mut cubeb_stream, panning: c_float) -> c_int;
     pub fn cubeb_stream_get_current_device(
         stream: *mut cubeb_stream,
         device: *mut *mut cubeb_device,
     ) -> c_int;
     pub fn cubeb_stream_device_destroy(
         stream: *mut cubeb_stream,
         devices: *mut cubeb_device,
     ) -> c_int;
--- a/third_party/rust/cubeb/.cargo-checksum.json
+++ b/third_party/rust/cubeb/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"9096d3058df22f6dde09f7eaf213f276924a19c32283cfda7a51b7c747b003b0","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","README.md":"408c573ec240927cf5b9c036098e94e374ec41f71991415422586f450586b214","examples/common/mod.rs":"a5e1b79fc2b4addff1e442879ba3dbcb1cf5973e76b9a62d97dd0042597480db","examples/devices.rs":"89e13542853995d1ae4a49d6829156efb29dd25c6caffdf22496c28c8263ffeb","examples/tone.rs":"8f5f9851b6d99f6f16c597fcb9312e3ef81769cbfb89341d2ea2522ca2e2214e","src/context.rs":"03511fa960a411728163e700edc2fd6cfbfcf09766ffe62ee82a2cbd08fdf243","src/frame.rs":"ed1e8f4576022d0c23106bb115125e5a2967b0375a10d0c54bbe99f04a70cc3f","src/lib.rs":"98e9280890551ac9305f2f808e315b6aa6bcd5781b8e96a078787ded0ef91e2a","src/log.rs":"704faeb31934dad6bc6d02e01caa85118754209bd559d30d03fcfa5cb8c1603c","src/sample.rs":"e23be3b691052001916f920ce9c1a0051bd097e39c9d34cbcb80ab8120265f45","src/stream.rs":"3ee0432f655cd42959cd5d8e75cb4fe2322e1f88fa5d9cc83e615ae229cdeb8a"},"package":"50f6a746cc3a80bdc96203e617d3bfc8988169c012c85c4ca4f1bad7862441bc"}
\ No newline at end of file
+{"files":{"Cargo.toml":"3f16c9c35795e9a05783518797fba3fd031ae46b61232ce0c05e13e5203506d7","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","README.md":"408c573ec240927cf5b9c036098e94e374ec41f71991415422586f450586b214","examples/common/mod.rs":"a5e1b79fc2b4addff1e442879ba3dbcb1cf5973e76b9a62d97dd0042597480db","examples/devices.rs":"89e13542853995d1ae4a49d6829156efb29dd25c6caffdf22496c28c8263ffeb","examples/tone.rs":"8f5f9851b6d99f6f16c597fcb9312e3ef81769cbfb89341d2ea2522ca2e2214e","src/context.rs":"03511fa960a411728163e700edc2fd6cfbfcf09766ffe62ee82a2cbd08fdf243","src/frame.rs":"ed1e8f4576022d0c23106bb115125e5a2967b0375a10d0c54bbe99f04a70cc3f","src/lib.rs":"98e9280890551ac9305f2f808e315b6aa6bcd5781b8e96a078787ded0ef91e2a","src/log.rs":"704faeb31934dad6bc6d02e01caa85118754209bd559d30d03fcfa5cb8c1603c","src/sample.rs":"e23be3b691052001916f920ce9c1a0051bd097e39c9d34cbcb80ab8120265f45","src/stream.rs":"3ee0432f655cd42959cd5d8e75cb4fe2322e1f88fa5d9cc83e615ae229cdeb8a"},"package":"3cbcdfde9ea319160af6eff068ffaa96aad3532e1b5c0ebc134614cfacacae24"}
\ No newline at end of file
--- a/third_party/rust/cubeb/Cargo.toml
+++ b/third_party/rust/cubeb/Cargo.toml
@@ -7,24 +7,24 @@
 #
 # 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 = "cubeb"
-version = "0.5.5"
+version = "0.6.2"
 authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"]
 description = "Bindings to libcubeb for interacting with system audio from rust.\n"
 homepage = "https://github.com/djg/cubeb-rs"
 readme = "README.md"
 keywords = ["cubeb"]
 categories = ["api-bindings"]
 license = "ISC"
 repository = "https://github.com/djg/cubeb-rs"
 [dependencies.cubeb-core]
-version = "0.5.5"
+version = "0.6.2"
 
 [features]
 gecko-in-tree = ["cubeb-core/gecko-in-tree"]
 [badges.circle-ci]
 repository = "djg/cubeb-rs"
deleted file mode 100644
--- a/third_party/rust/scoped-tls-0.1.0/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{"Cargo.toml":"ac2be902201c6ed727fc1a35d5d55322127f0f155a9b51dfb9caade37b383b68","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"9d85b54d8b58f56770bb280919b04b6387942c7b1aae6be380e7f6f144817230","appveyor.yml":"da991211b72fa6f231af7adb84c9fb72f5a9131d1c0a3d47b8ceffe5a82c8542","src/lib.rs":"31c17694802e227246b06d64be3b30f3e378e82d2ee010f42896a6734e1f7682"},"package":"f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"}
\ No newline at end of file
deleted file mode 100644
--- a/third_party/rust/scoped-tls-0.1.0/Cargo.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[package]
-name = "scoped-tls"
-version = "0.1.0"
-authors = ["Alex Crichton <alex@alexcrichton.com>"]
-license = "MIT/Apache-2.0"
-readme = "README.md"
-repository = "https://github.com/alexcrichton/scoped-tls"
-homepage = "https://github.com/alexcrichton/scoped-tls"
-documentation = "http://alexcrichton.com/scoped-tls"
-description = """
-Library implementation of the standard library's old `scoped_thread_local!`
-macro for providing scoped access to thread local storage (TLS) so any type can
-be stored into TLS.
-"""
deleted file mode 100644
--- a/third_party/rust/scoped-tls-0.1.0/README.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# scoped-tls
-
-[![Build Status](https://travis-ci.org/alexcrichton/scoped-tls.svg?branch=master)](https://travis-ci.org/alexcrichton/scoped-tls)
-[![Build status](https://ci.appveyor.com/api/projects/status/9tatexq47i3ee13k?svg=true)](https://ci.appveyor.com/project/alexcrichton/flate2-rs)
-
-[Documentation](http://alexcrichton.com/scoped-tls)
-
-A Rust library providing the old standard library's `scoped_thread_local!` macro
-as a library implementation on crates.io.
-
-```toml
-# Cargo.toml
-[dependencies]
-scoped-tls = "0.1"
-```
-
-# License
-
-`scoped-tls` 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.
deleted file mode 100644
--- a/third_party/rust/scoped-tls-0.1.0/appveyor.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-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
deleted file mode 100644
--- a/third_party/rust/scoped-tls-0.1.0/src/lib.rs
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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.
-
-//! Scoped thread-local storage
-//!
-//! This module provides the ability to generate *scoped* thread-local
-//! variables. In this sense, scoped indicates that thread local storage
-//! actually stores a reference to a value, and this reference is only placed
-//! in storage for a scoped amount of time.
-//!
-//! There are no restrictions on what types can be placed into a scoped
-//! variable, but all scoped variables are initialized to the equivalent of
-//! null. Scoped thread local storage is useful when a value is present for a known
-//! period of time and it is not required to relinquish ownership of the
-//! contents.
-//!
-//! # Examples
-//!
-//! ```
-//! #[macro_use]
-//! extern crate scoped_tls;
-//!
-//! scoped_thread_local!(static FOO: u32);
-//!
-//! # fn main() {
-//! // Initially each scoped slot is empty.
-//! assert!(!FOO.is_set());
-//!
-//! // When inserting a value, the value is only in place for the duration
-//! // of the closure specified.
-//! FOO.set(&1, || {
-//!     FOO.with(|slot| {
-//!         assert_eq!(*slot, 1);
-//!     });
-//! });
-//! # }
-//! ```
-
-#![deny(missing_docs, warnings)]
-
-use std::cell::Cell;
-use std::marker;
-use std::thread::LocalKey;
-
-#[macro_export]
-macro_rules! scoped_thread_local {
-    (static $name:ident: $ty:ty) => (
-        static $name: $crate::ScopedKey<$ty> = $crate::ScopedKey {
-            inner: {
-                thread_local!(static FOO: ::std::cell::Cell<usize> = {
-                    ::std::cell::Cell::new(0)
-                });
-                &FOO
-            },
-            _marker: ::std::marker::PhantomData,
-        };
-    )
-}
-
-/// Type representing a thread local storage key corresponding to a reference
-/// to the type parameter `T`.
-///
-/// Keys are statically allocated and can contain a reference to an instance of
-/// type `T` scoped to a particular lifetime. Keys provides two methods, `set`
-/// and `with`, both of which currently use closures to control the scope of
-/// their contents.
-pub struct ScopedKey<T> {
-    #[doc(hidden)]
-    pub inner: &'static LocalKey<Cell<usize>>,
-    #[doc(hidden)]
-    pub _marker: marker::PhantomData<T>,
-}
-
-unsafe impl<T> Sync for ScopedKey<T> {}
-
-impl<T> ScopedKey<T> {
-    /// Inserts a value into this scoped thread local storage slot for a
-    /// duration of a closure.
-    ///
-    /// While `cb` is running, the value `t` will be returned by `get` unless
-    /// this function is called recursively inside of `cb`.
-    ///
-    /// Upon return, this function will restore the previous value, if any
-    /// was available.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #[macro_use]
-    /// extern crate scoped_tls;
-    ///
-    /// scoped_thread_local!(static FOO: u32);
-    ///
-    /// # fn main() {
-    /// FOO.set(&100, || {
-    ///     let val = FOO.with(|v| *v);
-    ///     assert_eq!(val, 100);
-    ///
-    ///     // set can be called recursively
-    ///     FOO.set(&101, || {
-    ///         // ...
-    ///     });
-    ///
-    ///     // Recursive calls restore the previous value.
-    ///     let val = FOO.with(|v| *v);
-    ///     assert_eq!(val, 100);
-    /// });
-    /// # }
-    /// ```
-    pub fn set<F, R>(&'static self, t: &T, f: F) -> R
-        where F: FnOnce() -> R
-    {
-        struct Reset {
-            key: &'static LocalKey<Cell<usize>>,
-            val: usize,
-        }
-        impl Drop for Reset {
-            fn drop(&mut self) {
-                self.key.with(|c| c.set(self.val));
-            }
-        }
-        let prev = self.inner.with(|c| {
-            let prev = c.get();
-            c.set(t as *const T as usize);
-            prev
-        });
-        let _reset = Reset { key: self.inner, val: prev };
-        f()
-    }
-
-    /// Gets a value out of this scoped variable.
-    ///
-    /// This function takes a closure which receives the value of this
-    /// variable.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if `set` has not previously been called.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// #[macro_use]
-    /// extern crate scoped_tls;
-    ///
-    /// scoped_thread_local!(static FOO: u32);
-    ///
-    /// # fn main() {
-    /// FOO.with(|slot| {
-    ///     // work with `slot`
-    /// # drop(slot);
-    /// });
-    /// # }
-    /// ```
-    pub fn with<F, R>(&'static self, f: F) -> R
-        where F: FnOnce(&T) -> R
-    {
-        let val = self.inner.with(|c| c.get());
-        assert!(val != 0, "cannot access a scoped thread local \
-                           variable without calling `set` first");
-        unsafe {
-            f(&*(val as *const T))
-        }
-    }
-
-    /// Test whether this TLS key has been `set` for the current thread.
-    pub fn is_set(&'static self) -> bool {
-        self.inner.with(|c| c.get() != 0)
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use std::cell::Cell;
-    use std::sync::mpsc::{channel, Sender};
-    use std::thread;
-
-    scoped_thread_local!(static FOO: u32);
-
-    #[test]
-    fn smoke() {
-        scoped_thread_local!(static BAR: u32);
-
-        assert!(!BAR.is_set());
-        BAR.set(&1, || {
-            assert!(BAR.is_set());
-            BAR.with(|slot| {
-                assert_eq!(*slot, 1);
-            });
-        });
-        assert!(!BAR.is_set());
-    }
-
-    #[test]
-    fn cell_allowed() {
-        scoped_thread_local!(static BAR: Cell<u32>);
-
-        BAR.set(&Cell::new(1), || {
-            BAR.with(|slot| {
-                assert_eq!(slot.get(), 1);
-            });
-        });
-    }
-
-    #[test]
-    fn scope_item_allowed() {
-        assert!(!FOO.is_set());
-        FOO.set(&1, || {
-            assert!(FOO.is_set());
-            FOO.with(|slot| {
-                assert_eq!(*slot, 1);
-            });
-        });
-        assert!(!FOO.is_set());
-    }
-
-    #[test]
-    fn panic_resets() {
-        struct Check(Sender<u32>);
-        impl Drop for Check {
-            fn drop(&mut self) {
-                FOO.with(|r| {
-                    self.0.send(*r).unwrap();
-                })
-            }
-        }
-
-        let (tx, rx) = channel();
-        let t = thread::spawn(|| {
-            FOO.set(&1, || {
-                let _r = Check(tx);
-
-                FOO.set(&2, || {
-                    panic!()
-                });
-            });
-        });
-
-        assert_eq!(rx.recv().unwrap(), 1);
-        assert!(t.join().is_err());
-    }
-}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver-0.7.0/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{"Cargo.toml":"cfbf903b8a7aea7a5481ccafeaf1d368e882e7a0b270e8bd86a8177ee21c7d63","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"bb80bfbd16bf7dc34de45891c21333c42590d5c5c10e8ba0ed59549fce5af1dd","src/lib.rs":"cb1725a8bb90c1043f187c6ba504d0a9d07793e2f39f5205f926c58849311770","src/version.rs":"f871fe41495d1f7b1230ed91fab6fb3f577c455c4a7f196fdab35bcff566b898","src/version_req.rs":"093f2ac08f2bc8fcf6a93ae0fc333eccc1ea04932e0c0b26835a952bb220eca1","tests/deprecation.rs":"b5ec79e19d61968d05b96b876c449e54d43cbd1762c6e63c23c3470f9db56292","tests/regression.rs":"180b699ad029b81e6135d42f0a8e6d782177bc29a41132f875ee6f8607a46b56","tests/serde.rs":"271d6d47ca8ee2600fe4476a14192f8879f21e5f66fb0f202d93d71fd5ffa368"},"package":"3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver-0.7.0/Cargo.toml
@@ -0,0 +1,28 @@
+[package]
+
+name = "semver"
+version = "0.7.0"
+authors = ["Steve Klabnik <steve@steveklabnik.com>", "The Rust Project Developers"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/steveklabnik/semver"
+homepage = "https://docs.rs/crate/semver/"
+documentation = "https://docs.rs/crate/semver/"
+description = """
+Semantic version parsing and comparison.
+"""
+
+[dependencies]
+semver-parser = "0.7.0"
+serde = { version = "1.0", optional = true }
+
+[features]
+default = []
+
+# are we testing on CI?
+ci = ["serde"]
+
+[dev-dependencies]
+crates-index = "0.5.0"
+tempdir = "0.3.4"
+serde_json = "1.0"
+serde_derive = "1.0"
rename from third_party/rust/scoped-tls-0.1.0/LICENSE-APACHE
rename to third_party/rust/semver-0.7.0/LICENSE-APACHE
rename from third_party/rust/scoped-tls-0.1.0/LICENSE-MIT
rename to third_party/rust/semver-0.7.0/LICENSE-MIT
--- a/third_party/rust/scoped-tls-0.1.0/LICENSE-MIT
+++ b/third_party/rust/semver-0.7.0/LICENSE-MIT
@@ -1,9 +1,9 @@
-Copyright (c) 2014 Alex Crichton
+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
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver-0.7.0/README.md
@@ -0,0 +1,103 @@
+semver
+======
+
+Semantic version parsing and comparison.
+
+[![Build Status](https://api.travis-ci.org/steveklabnik/semver.svg?branch=master)](https://travis-ci.org/steveklabnik/semver)
+
+[Documentation](https://steveklabnik.github.io/semver)
+
+Semantic versioning (see http://semver.org/) is a set of rules for
+assigning version numbers.
+
+## SemVer and the Rust ecosystem
+
+Rust itself follows the SemVer specification, as does its standard libraries. The two are
+not tied together.
+
+[Cargo](https://crates.io), Rust's package manager, uses SemVer to determine which versions of
+packages you need installed.
+
+## Installation
+
+To use `semver`, add this to your `[dependencies]` section:
+
+```toml
+semver = "0.6.0"
+```
+
+And this to your crate root:
+
+```rust
+extern crate semver;
+```
+
+## Versions
+
+At its simplest, the `semver` crate allows you to construct `Version` objects using the `parse`
+method:
+
+```rust
+use semver::Version;
+
+assert!(Version::parse("1.2.3") == Ok(Version {
+   major: 1,
+   minor: 2,
+   patch: 3,
+   pre: vec!(),
+   build: vec!(),
+}));
+```
+
+If you have multiple `Version`s, you can use the usual comparison operators to compare them:
+
+```rust
+use semver::Version;
+
+assert!(Version::parse("1.2.3-alpha")  != Version::parse("1.2.3-beta"));
+assert!(Version::parse("1.2.3-alpha2") >  Version::parse("1.2.0"));
+```
+
+## Requirements
+
+The `semver` crate also provides the ability to compare requirements, which are more complex
+comparisons.
+
+For example, creating a requirement that only matches versions greater than or
+equal to 1.0.0:
+
+```rust
+use semver::Version;
+use semver::VersionReq;
+
+let r = VersionReq::parse(">= 1.0.0").unwrap();
+let v = Version::parse("1.0.0").unwrap();
+
+assert!(r.to_string() == ">= 1.0.0".to_string());
+assert!(r.matches(&v))
+```
+
+It also allows parsing of `~x.y.z` and `^x.y.z` requirements as defined at
+https://www.npmjs.org/doc/misc/semver.html
+
+**Tilde requirements** specify a minimal version with some updates:
+
+```notrust
+~1.2.3 := >=1.2.3 <1.3.0
+~1.2   := >=1.2.0 <1.3.0
+~1     := >=1.0.0 <2.0.0
+```
+
+**Caret requirements** allow SemVer compatible updates to a specified version,
+`0.x` and `0.x+1` are not considered compatible, but `1.x` and `1.x+1` are.
+
+`0.0.x` is not considered compatible with any other version.
+Missing minor and patch versions are desugared to `0` but allow flexibility for that value.
+
+```notrust
+^1.2.3 := >=1.2.3 <2.0.0
+^0.2.3 := >=0.2.3 <0.3.0
+^0.0.3 := >=0.0.3 <0.0.4
+^0.0   := >=0.0.0 <0.1.0
+^0     := >=0.0.0 <1.0.0
+```
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver-0.7.0/src/lib.rs
@@ -0,0 +1,182 @@
+// Copyright 2012-2013 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.
+
+//! Semantic version parsing and comparison.
+//!
+//! Semantic versioning (see http://semver.org/) is a set of rules for
+//! assigning version numbers.
+//!
+//! ## SemVer overview
+//!
+//! Given a version number MAJOR.MINOR.PATCH, increment the:
+//!
+//! 1. MAJOR version when you make incompatible API changes,
+//! 2. MINOR version when you add functionality in a backwards-compatible
+//!    manner, and
+//! 3. PATCH version when you make backwards-compatible bug fixes.
+//!
+//! Additional labels for pre-release and build metadata are available as
+//! extensions to the MAJOR.MINOR.PATCH format.
+//!
+//! Any references to 'the spec' in this documentation refer to [version 2.0 of
+//! the SemVer spec](http://semver.org/spec/v2.0.0.html).
+//!
+//! ## SemVer and the Rust ecosystem
+//!
+//! Rust itself follows the SemVer specification, as does its standard
+//! libraries. The two are not tied together.
+//!
+//! [Cargo](http://crates.io), Rust's package manager, uses SemVer to determine
+//! which versions of packages you need installed.
+//!
+//! ## Versions
+//!
+//! At its simplest, the `semver` crate allows you to construct `Version`
+//! objects using the `parse` method:
+//!
+//! ```{rust}
+//! use semver::Version;
+//!
+//! assert!(Version::parse("1.2.3") == Ok(Version {
+//!    major: 1,
+//!    minor: 2,
+//!    patch: 3,
+//!    pre: vec!(),
+//!    build: vec!(),
+//! }));
+//! ```
+//!
+//! If you have multiple `Version`s, you can use the usual comparison operators
+//! to compare them:
+//!
+//! ```{rust}
+//! use semver::Version;
+//!
+//! assert!(Version::parse("1.2.3-alpha") != Version::parse("1.2.3-beta"));
+//! assert!(Version::parse("1.2.3-alpha2") >  Version::parse("1.2.0"));
+//! ```
+//!
+//! If you explicitly need to modify a Version, SemVer also allows you to
+//! increment the major, minor, and patch numbers in accordance with the spec.
+//!
+//! Please note that in order to do this, you must use a mutable Version:
+//!
+//! ```{rust}
+//! use semver::Version;
+//!
+//! let mut bugfix_release = Version::parse("1.0.0").unwrap();
+//! bugfix_release.increment_patch();
+//!
+//! assert_eq!(Ok(bugfix_release), Version::parse("1.0.1"));
+//! ```
+//!
+//! When incrementing the minor version number, the patch number resets to zero
+//! (in accordance with section 7 of the spec)
+//!
+//! ```{rust}
+//! use semver::Version;
+//!
+//! let mut feature_release = Version::parse("1.4.6").unwrap();
+//! feature_release.increment_minor();
+//!
+//! assert_eq!(Ok(feature_release), Version::parse("1.5.0"));
+//! ```
+//!
+//! Similarly, when incrementing the major version number, the patch and minor
+//! numbers reset to zero (in accordance with section 8 of the spec)
+//!
+//! ```{rust}
+//! use semver::Version;
+//!
+//! let mut chrome_release = Version::parse("41.5.5377").unwrap();
+//! chrome_release.increment_major();
+//!
+//! assert_eq!(Ok(chrome_release), Version::parse("42.0.0"));
+//! ```
+//!
+//! ## Requirements
+//!
+//! The `semver` crate also provides the ability to compare requirements, which
+//! are more complex comparisons.
+//!
+//! For example, creating a requirement that only matches versions greater than
+//! or equal to 1.0.0:
+//!
+//! ```{rust}
+//! # #![allow(unstable)]
+//! use semver::Version;
+//! use semver::VersionReq;
+//!
+//! let r = VersionReq::parse(">= 1.0.0").unwrap();
+//! let v = Version::parse("1.0.0").unwrap();
+//!
+//! assert!(r.to_string() == ">= 1.0.0".to_string());
+//! assert!(r.matches(&v))
+//! ```
+//!
+//! It also allows parsing of `~x.y.z` and `^x.y.z` requirements as defined at
+//! https://www.npmjs.org/doc/misc/semver.html
+//!
+//! **Tilde requirements** specify a minimal version with some updates:
+//!
+//! ```notrust
+//! ~1.2.3 := >=1.2.3 <1.3.0
+//! ~1.2   := >=1.2.0 <1.3.0
+//! ~1     := >=1.0.0 <2.0.0
+//! ```
+//!
+//! **Caret requirements** allow SemVer compatible updates to a specified
+//! verion, `0.x` and `0.x+1` are not considered compatible, but `1.x` and
+//! `1.x+1` are.
+//!
+//! `0.0.x` is not considered compatible with any other version.
+//! Missing minor and patch versions are desugared to `0` but allow flexibility
+//! for that value.
+//!
+//! ```notrust
+//! ^1.2.3 := >=1.2.3 <2.0.0
+//! ^0.2.3 := >=0.2.3 <0.3.0
+//! ^0.0.3 := >=0.0.3 <0.0.4
+//! ^0.0   := >=0.0.0 <0.1.0
+//! ^0     := >=0.0.0 <1.0.0
+//! ```
+//!
+//! **Wildcard requirements** allows parsing of version requirements of the
+//! formats `*`, `x.*` and `x.y.*`.
+//!
+//! ```notrust
+//! *     := >=0.0.0
+//! 1.*   := >=1.0.0 <2.0.0
+//! 1.2.* := >=1.2.0 <1.3.0
+//! ```
+
+#![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")]
+#![deny(missing_docs)]
+#![cfg_attr(test, deny(warnings))]
+
+extern crate semver_parser;
+
+// Serialization and deserialization support for version numbers
+#[cfg(feature = "serde")]
+extern crate serde;
+
+// We take the common approach of keeping our own module system private, and
+// just re-exporting the interface that we want.
+
+pub use version::{Version, Identifier, SemVerError};
+pub use version::Identifier::{Numeric, AlphaNumeric};
+pub use version_req::{VersionReq, ReqParseError};
+
+// SemVer-compliant versions.
+mod version;
+
+// advanced version comparisons
+mod version_req;
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver-0.7.0/src/version.rs
@@ -0,0 +1,736 @@
+// Copyright 2012-2013 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 `version` module gives you tools to create and compare SemVer-compliant
+//! versions.
+
+use std::cmp::{self, Ordering};
+use std::fmt;
+use std::hash;
+use std::error::Error;
+
+use std::result;
+use std::str;
+
+use semver_parser;
+
+#[cfg(feature = "serde")]
+use serde::ser::{Serialize, Serializer};
+#[cfg(feature = "serde")]
+use serde::de::{self, Deserialize, Deserializer, Visitor};
+
+/// An identifier in the pre-release or build metadata.
+///
+/// See sections 9 and 10 of the spec for more about pre-release identifers and
+/// build metadata.
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+pub enum Identifier {
+    /// An identifier that's solely numbers.
+    Numeric(u64),
+    /// An identifier with letters and numbers.
+    AlphaNumeric(String),
+}
+
+impl From<semver_parser::version::Identifier> for Identifier {
+    fn from(other: semver_parser::version::Identifier) -> Identifier {
+        match other {
+            semver_parser::version::Identifier::Numeric(n) => Identifier::Numeric(n),
+            semver_parser::version::Identifier::AlphaNumeric(s) => Identifier::AlphaNumeric(s),
+        }
+    }
+}
+
+impl fmt::Display for Identifier {
+    #[inline]
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Identifier::Numeric(ref n) => fmt::Display::fmt(n, f),
+            Identifier::AlphaNumeric(ref s) => fmt::Display::fmt(s, f),
+        }
+    }
+}
+
+#[cfg(feature = "serde")]
+impl Serialize for Identifier {
+    fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
+        where S: Serializer
+    {
+        // Serialize Identifier as a number or string.
+        match *self {
+            Identifier::Numeric(n) => serializer.serialize_u64(n),
+            Identifier::AlphaNumeric(ref s) => serializer.serialize_str(s),
+        }
+    }
+}
+
+#[cfg(feature = "serde")]
+impl<'de> Deserialize<'de> for Identifier {
+    fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
+        where D: Deserializer<'de>
+    {
+        struct IdentifierVisitor;
+
+        // Deserialize Identifier from a number or string.
+        impl<'de> Visitor<'de> for IdentifierVisitor {
+            type Value = Identifier;
+
+            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+                formatter.write_str("a SemVer pre-release or build identifier")
+            }
+
+            fn visit_u64<E>(self, numeric: u64) -> result::Result<Self::Value, E>
+                where E: de::Error
+            {
+                Ok(Identifier::Numeric(numeric))
+            }
+
+            fn visit_str<E>(self, alphanumeric: &str) -> result::Result<Self::Value, E>
+                where E: de::Error
+            {
+                Ok(Identifier::AlphaNumeric(alphanumeric.to_owned()))
+            }
+        }
+
+        deserializer.deserialize_any(IdentifierVisitor)
+    }
+}
+
+/// Represents a version number conforming to the semantic versioning scheme.
+#[derive(Clone, Eq, Debug)]
+pub struct Version {
+    /// The major version, to be incremented on incompatible changes.
+    pub major: u64,
+    /// The minor version, to be incremented when functionality is added in a
+    /// backwards-compatible manner.
+    pub minor: u64,
+    /// The patch version, to be incremented when backwards-compatible bug
+    /// fixes are made.
+    pub patch: u64,
+    /// The pre-release version identifier, if one exists.
+    pub pre: Vec<Identifier>,
+    /// The build metadata, ignored when determining version precedence.
+    pub build: Vec<Identifier>,
+}
+
+impl From<semver_parser::version::Version> for Version {
+    fn from(other: semver_parser::version::Version) -> Version {
+        Version {
+            major: other.major,
+            minor: other.minor,
+            patch: other.patch,
+            pre: other.pre.into_iter().map(From::from).collect(),
+            build: other.build.into_iter().map(From::from).collect(),
+        }
+    }
+}
+
+#[cfg(feature = "serde")]
+impl Serialize for Version {
+    fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
+        where S: Serializer
+    {
+        // Serialize Version as a string.
+        serializer.collect_str(self)
+    }
+}
+
+#[cfg(feature = "serde")]
+impl<'de> Deserialize<'de> for Version {
+    fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
+        where D: Deserializer<'de>
+    {
+        struct VersionVisitor;
+
+        // Deserialize Version from a string.
+        impl<'de> Visitor<'de> for VersionVisitor {
+            type Value = Version;
+
+            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+                formatter.write_str("a SemVer version as a string")
+            }
+
+            fn visit_str<E>(self, v: &str) -> result::Result<Self::Value, E>
+                where E: de::Error
+            {
+                Version::parse(v).map_err(de::Error::custom)
+            }
+        }
+
+        deserializer.deserialize_str(VersionVisitor)
+    }
+}
+
+/// An error type for this crate
+///
+/// Currently, just a generic error. Will make this nicer later.
+#[derive(Clone,PartialEq,Debug,PartialOrd)]
+pub enum SemVerError {
+    /// An error ocurred while parsing.
+    ParseError(String),
+}
+
+impl fmt::Display for SemVerError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            &SemVerError::ParseError(ref m) => write!(f, "{}", m),
+        }
+    }
+}
+
+impl Error for SemVerError {
+    fn description(&self) -> &str {
+        match self {
+            &SemVerError::ParseError(ref m) => m,
+        }
+    }
+}
+
+/// A Result type for errors
+pub type Result<T> = result::Result<T, SemVerError>;
+
+impl Version {
+    /// Parse a string into a semver object.
+    pub fn parse(version: &str) -> Result<Version> {
+        let res = semver_parser::version::parse(version);
+
+        match res {
+            // Convert plain String error into proper ParseError
+            Err(e) => Err(SemVerError::ParseError(e)),
+            Ok(v) => Ok(From::from(v)),
+        }
+    }
+
+    /// Clears the build metadata
+    fn clear_metadata(&mut self) {
+        self.build = Vec::new();
+        self.pre = Vec::new();
+    }
+
+    /// Increments the patch number for this Version (Must be mutable)
+    pub fn increment_patch(&mut self) {
+        self.patch += 1;
+        self.clear_metadata();
+    }
+
+    /// Increments the minor version number for this Version (Must be mutable)
+    ///
+    /// As instructed by section 7 of the spec, the patch number is reset to 0.
+    pub fn increment_minor(&mut self) {
+        self.minor += 1;
+        self.patch = 0;
+        self.clear_metadata();
+    }
+
+    /// Increments the major version number for this Version (Must be mutable)
+    ///
+    /// As instructed by section 8 of the spec, the minor and patch numbers are
+    /// reset to 0
+    pub fn increment_major(&mut self) {
+        self.major += 1;
+        self.minor = 0;
+        self.patch = 0;
+        self.clear_metadata();
+    }
+
+    /// Checks to see if the current Version is in pre-release status
+    pub fn is_prerelease(&self) -> bool {
+        !self.pre.is_empty()
+    }
+}
+
+impl str::FromStr for Version {
+    type Err = SemVerError;
+
+    fn from_str(s: &str) -> Result<Version> {
+        Version::parse(s)
+    }
+}
+
+impl fmt::Display for Version {
+    #[inline]
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        try!(write!(f, "{}.{}.{}", self.major, self.minor, self.patch));
+        if !self.pre.is_empty() {
+            try!(write!(f, "-"));
+            for (i, x) in self.pre.iter().enumerate() {
+                if i != 0 {
+                    try!(write!(f, "."))
+                }
+                try!(write!(f, "{}", x));
+            }
+        }
+        if !self.build.is_empty() {
+            try!(write!(f, "+"));
+            for (i, x) in self.build.iter().enumerate() {
+                if i != 0 {
+                    try!(write!(f, "."))
+                }
+                try!(write!(f, "{}", x));
+            }
+        }
+        Ok(())
+    }
+}
+
+impl cmp::PartialEq for Version {
+    #[inline]
+    fn eq(&self, other: &Version) -> bool {
+        // We should ignore build metadata here, otherwise versions v1 and v2
+        // can exist such that !(v1 < v2) && !(v1 > v2) && v1 != v2, which
+        // violate strict total ordering rules.
+        self.major == other.major && self.minor == other.minor && self.patch == other.patch &&
+        self.pre == other.pre
+    }
+}
+
+impl cmp::PartialOrd for Version {
+    fn partial_cmp(&self, other: &Version) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl cmp::Ord for Version {
+    fn cmp(&self, other: &Version) -> Ordering {
+        match self.major.cmp(&other.major) {
+            Ordering::Equal => {}
+            r => return r,
+        }
+
+        match self.minor.cmp(&other.minor) {
+            Ordering::Equal => {}
+            r => return r,
+        }
+
+        match self.patch.cmp(&other.patch) {
+            Ordering::Equal => {}
+            r => return r,
+        }
+
+        // NB: semver spec says 0.0.0-pre < 0.0.0
+        // but the version of ord defined for vec
+        // says that [] < [pre] so we alter it here
+        match (self.pre.len(), other.pre.len()) {
+            (0, 0) => Ordering::Equal,
+            (0, _) => Ordering::Greater,
+            (_, 0) => Ordering::Less,
+            (_, _) => self.pre.cmp(&other.pre),
+        }
+    }
+}
+
+impl hash::Hash for Version {
+    fn hash<H: hash::Hasher>(&self, into: &mut H) {
+        self.major.hash(into);
+        self.minor.hash(into);
+        self.patch.hash(into);
+        self.pre.hash(into);
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use std::result;
+    use super::Version;
+    use super::Identifier;
+    use super::SemVerError;
+
+    #[test]
+    fn test_parse() {
+        fn parse_error(e: &str) -> result::Result<Version, SemVerError> {
+            return Err(SemVerError::ParseError(e.to_string()));
+        }
+
+        assert_eq!(Version::parse(""),
+                   parse_error("Error parsing major identifier"));
+        assert_eq!(Version::parse("  "),
+                   parse_error("Error parsing major identifier"));
+        assert_eq!(Version::parse("1"),
+                   parse_error("Expected dot"));
+        assert_eq!(Version::parse("1.2"),
+                   parse_error("Expected dot"));
+        assert_eq!(Version::parse("1.2.3-"),
+                   parse_error("Error parsing prerelease"));
+        assert_eq!(Version::parse("a.b.c"),
+                   parse_error("Error parsing major identifier"));
+        assert_eq!(Version::parse("1.2.3 abc"),
+                   parse_error("Extra junk after valid version:  abc"));
+
+        assert_eq!(Version::parse("1.2.3"),
+                   Ok(Version {
+                       major: 1,
+                       minor: 2,
+                       patch: 3,
+                       pre: Vec::new(),
+                       build: Vec::new(),
+                   }));
+        assert_eq!(Version::parse("  1.2.3  "),
+                   Ok(Version {
+                       major: 1,
+                       minor: 2,
+                       patch: 3,
+                       pre: Vec::new(),
+                       build: Vec::new(),
+                   }));
+        assert_eq!(Version::parse("1.2.3-alpha1"),
+                   Ok(Version {
+                       major: 1,
+                       minor: 2,
+                       patch: 3,
+                       pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],
+                       build: Vec::new(),
+                   }));
+        assert_eq!(Version::parse("  1.2.3-alpha1  "),
+                   Ok(Version {
+                       major: 1,
+                       minor: 2,
+                       patch: 3,
+                       pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],
+                       build: Vec::new(),
+                   }));
+        assert_eq!(Version::parse("1.2.3+build5"),
+                   Ok(Version {
+                       major: 1,
+                       minor: 2,
+                       patch: 3,
+                       pre: Vec::new(),
+                       build: vec![Identifier::AlphaNumeric(String::from("build5"))],
+                   }));
+        assert_eq!(Version::parse("  1.2.3+build5  "),
+                   Ok(Version {
+                       major: 1,
+                       minor: 2,
+                       patch: 3,
+                       pre: Vec::new(),
+                       build: vec![Identifier::AlphaNumeric(String::from("build5"))],
+                   }));
+        assert_eq!(Version::parse("1.2.3-alpha1+build5"),
+                   Ok(Version {
+                       major: 1,
+                       minor: 2,
+                       patch: 3,
+                       pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],
+                       build: vec![Identifier::AlphaNumeric(String::from("build5"))],
+                   }));
+        assert_eq!(Version::parse("  1.2.3-alpha1+build5  "),
+                   Ok(Version {
+                       major: 1,
+                       minor: 2,
+                       patch: 3,
+                       pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))],
+                       build: vec![Identifier::AlphaNumeric(String::from("build5"))],
+                   }));
+        assert_eq!(Version::parse("1.2.3-1.alpha1.9+build5.7.3aedf  "),
+                   Ok(Version {
+                       major: 1,
+                       minor: 2,
+                       patch: 3,
+                       pre: vec![Identifier::Numeric(1),
+                      Identifier::AlphaNumeric(String::from("alpha1")),
+                      Identifier::Numeric(9),
+            ],
+                       build: vec![Identifier::AlphaNumeric(String::from("build5")),
+                        Identifier::Numeric(7),
+                        Identifier::AlphaNumeric(String::from("3aedf")),
+            ],
+                   }));
+        assert_eq!(Version::parse("0.4.0-beta.1+0851523"),
+                   Ok(Version {
+                       major: 0,
+                       minor: 4,
+                       patch: 0,
+                       pre: vec![Identifier::AlphaNumeric(String::from("beta")),
+                      Identifier::Numeric(1),
+            ],
+                       build: vec![Identifier::AlphaNumeric(String::from("0851523"))],
+                   }));
+
+    }
+
+    #[test]
+    fn test_increment_patch() {
+        let mut buggy_release = Version::parse("0.1.0").unwrap();
+        buggy_release.increment_patch();
+        assert_eq!(buggy_release, Version::parse("0.1.1").unwrap());
+    }
+
+    #[test]
+    fn test_increment_minor() {
+        let mut feature_release = Version::parse("1.4.6").unwrap();
+        feature_release.increment_minor();
+        assert_eq!(feature_release, Version::parse("1.5.0").unwrap());
+    }
+
+    #[test]
+    fn test_increment_major() {
+        let mut chrome_release = Version::parse("46.1.246773").unwrap();
+        chrome_release.increment_major();
+        assert_eq!(chrome_release, Version::parse("47.0.0").unwrap());
+    }
+
+    #[test]
+    fn test_increment_keep_prerelease() {
+        let mut release = Version::parse("1.0.0-alpha").unwrap();
+        release.increment_patch();
+
+        assert_eq!(release, Version::parse("1.0.1").unwrap());
+
+        release.increment_minor();
+
+        assert_eq!(release, Version::parse("1.1.0").unwrap());
+
+        release.increment_major();
+
+        assert_eq!(release, Version::parse("2.0.0").unwrap());
+    }
+
+
+    #[test]
+    fn test_increment_clear_metadata() {
+        let mut release = Version::parse(&