Bug 1396824 - Part 2: Revendor dependencies. r=ato
authorBastien Orivel <eijebong@bananium.fr>
Fri, 21 Jun 2019 17:18:50 +0000
changeset 542763 4d31fcd3085d87085a42fafeea827d41a17890d6
parent 542762 dbb1c8fa2abac56bab990cff66d9399b99cd1e80
child 542764 9737fcd4ec9257efb8e7d3e5bb52275b7b3f7396
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersato
bugs1396824
milestone69.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 1396824 - Part 2: Revendor dependencies. r=ato Differential Revision: https://phabricator.services.mozilla.com/D34632
third_party/rust/crossbeam-channel/.cargo-checksum.json
third_party/rust/crossbeam-channel/CHANGELOG.md
third_party/rust/crossbeam-channel/Cargo.toml
third_party/rust/crossbeam-channel/LICENSE-APACHE
third_party/rust/crossbeam-channel/LICENSE-MIT
third_party/rust/crossbeam-channel/LICENSE-THIRD-PARTY
third_party/rust/crossbeam-channel/README.md
third_party/rust/crossbeam-channel/examples/fibonacci.rs
third_party/rust/crossbeam-channel/examples/matching.rs
third_party/rust/crossbeam-channel/examples/stopwatch.rs
third_party/rust/crossbeam-channel/src/channel.rs
third_party/rust/crossbeam-channel/src/context.rs
third_party/rust/crossbeam-channel/src/counter.rs
third_party/rust/crossbeam-channel/src/err.rs
third_party/rust/crossbeam-channel/src/flavors/after.rs
third_party/rust/crossbeam-channel/src/flavors/array.rs
third_party/rust/crossbeam-channel/src/flavors/list.rs
third_party/rust/crossbeam-channel/src/flavors/mod.rs
third_party/rust/crossbeam-channel/src/flavors/never.rs
third_party/rust/crossbeam-channel/src/flavors/tick.rs
third_party/rust/crossbeam-channel/src/flavors/zero.rs
third_party/rust/crossbeam-channel/src/lib.rs
third_party/rust/crossbeam-channel/src/select.rs
third_party/rust/crossbeam-channel/src/select_macro.rs
third_party/rust/crossbeam-channel/src/utils.rs
third_party/rust/crossbeam-channel/src/waker.rs
third_party/rust/crossbeam-channel/tests/after.rs
third_party/rust/crossbeam-channel/tests/array.rs
third_party/rust/crossbeam-channel/tests/golang.rs
third_party/rust/crossbeam-channel/tests/iter.rs
third_party/rust/crossbeam-channel/tests/list.rs
third_party/rust/crossbeam-channel/tests/mpsc.rs
third_party/rust/crossbeam-channel/tests/never.rs
third_party/rust/crossbeam-channel/tests/ready.rs
third_party/rust/crossbeam-channel/tests/select.rs
third_party/rust/crossbeam-channel/tests/select_macro.rs
third_party/rust/crossbeam-channel/tests/thread_locals.rs
third_party/rust/crossbeam-channel/tests/tick.rs
third_party/rust/crossbeam-channel/tests/zero.rs
third_party/rust/crossbeam-deque/.cargo-checksum.json
third_party/rust/crossbeam-deque/CHANGELOG.md
third_party/rust/crossbeam-deque/Cargo.toml
third_party/rust/crossbeam-deque/LICENSE-MIT
third_party/rust/crossbeam-deque/README.md
third_party/rust/crossbeam-deque/src/lib.rs
third_party/rust/crossbeam-deque/tests/fifo.rs
third_party/rust/crossbeam-deque/tests/lifo.rs
third_party/rust/crossbeam-epoch/.cargo-checksum.json
third_party/rust/crossbeam-epoch/CHANGELOG.md
third_party/rust/crossbeam-epoch/Cargo.toml
third_party/rust/crossbeam-epoch/LICENSE-MIT
third_party/rust/crossbeam-epoch/README.md
third_party/rust/crossbeam-epoch/benches/defer.rs
third_party/rust/crossbeam-epoch/benches/flush.rs
third_party/rust/crossbeam-epoch/benches/pin.rs
third_party/rust/crossbeam-epoch/examples/sanitize.rs
third_party/rust/crossbeam-epoch/examples/treiber_stack.rs
third_party/rust/crossbeam-epoch/src/atomic.rs
third_party/rust/crossbeam-epoch/src/collector.rs
third_party/rust/crossbeam-epoch/src/default.rs
third_party/rust/crossbeam-epoch/src/deferred.rs
third_party/rust/crossbeam-epoch/src/epoch.rs
third_party/rust/crossbeam-epoch/src/guard.rs
third_party/rust/crossbeam-epoch/src/internal.rs
third_party/rust/crossbeam-epoch/src/lib.rs
third_party/rust/crossbeam-epoch/src/sync/list.rs
third_party/rust/crossbeam-epoch/src/sync/queue.rs
third_party/rust/crossbeam-utils-0.3.2/.cargo-checksum.json
third_party/rust/crossbeam-utils-0.3.2/CHANGELOG.md
third_party/rust/crossbeam-utils-0.3.2/Cargo.toml
third_party/rust/crossbeam-utils-0.3.2/LICENSE-APACHE
third_party/rust/crossbeam-utils-0.3.2/LICENSE-MIT
third_party/rust/crossbeam-utils-0.3.2/README.md
third_party/rust/crossbeam-utils-0.3.2/src/cache_padded.rs
third_party/rust/crossbeam-utils-0.3.2/src/consume.rs
third_party/rust/crossbeam-utils-0.3.2/src/lib.rs
third_party/rust/crossbeam-utils-0.3.2/src/scoped.rs
third_party/rust/crossbeam-utils/.cargo-checksum.json
third_party/rust/crossbeam-utils/CHANGELOG.md
third_party/rust/crossbeam-utils/Cargo.toml
third_party/rust/crossbeam-utils/README.md
third_party/rust/crossbeam-utils/benches/atomic_cell.rs
third_party/rust/crossbeam-utils/src/atomic/atomic_cell.rs
third_party/rust/crossbeam-utils/src/atomic/mod.rs
third_party/rust/crossbeam-utils/src/backoff.rs
third_party/rust/crossbeam-utils/src/lib.rs
third_party/rust/crossbeam-utils/src/sync/mod.rs
third_party/rust/crossbeam-utils/src/sync/sharded_lock.rs
third_party/rust/crossbeam-utils/src/sync/wait_group.rs
third_party/rust/crossbeam-utils/src/thread.rs
third_party/rust/crossbeam-utils/tests/sharded_lock.rs
third_party/rust/crossbeam-utils/tests/wait_group.rs
third_party/rust/headers-core/.cargo-checksum.json
third_party/rust/headers-core/Cargo.toml
third_party/rust/headers-core/LICENSE
third_party/rust/headers-core/README.md
third_party/rust/headers-core/src/lib.rs
third_party/rust/headers-derive/.cargo-checksum.json
third_party/rust/headers-derive/Cargo.toml
third_party/rust/headers-derive/LICENSE
third_party/rust/headers-derive/README.md
third_party/rust/headers-derive/src/lib.rs
third_party/rust/headers/.cargo-checksum.json
third_party/rust/headers/Cargo.toml
third_party/rust/headers/LICENSE
third_party/rust/headers/README.md
third_party/rust/headers/src/common/accept_ranges.rs
third_party/rust/headers/src/common/access_control_allow_credentials.rs
third_party/rust/headers/src/common/access_control_allow_headers.rs
third_party/rust/headers/src/common/access_control_allow_methods.rs
third_party/rust/headers/src/common/access_control_allow_origin.rs
third_party/rust/headers/src/common/access_control_expose_headers.rs
third_party/rust/headers/src/common/access_control_max_age.rs
third_party/rust/headers/src/common/access_control_request_headers.rs
third_party/rust/headers/src/common/access_control_request_method.rs
third_party/rust/headers/src/common/allow.rs
third_party/rust/headers/src/common/authorization.rs
third_party/rust/headers/src/common/cache_control.rs
third_party/rust/headers/src/common/connection.rs
third_party/rust/headers/src/common/content_disposition.rs
third_party/rust/headers/src/common/content_encoding.rs
third_party/rust/headers/src/common/content_length.rs
third_party/rust/headers/src/common/content_location.rs
third_party/rust/headers/src/common/content_range.rs
third_party/rust/headers/src/common/content_type.rs
third_party/rust/headers/src/common/cookie.rs
third_party/rust/headers/src/common/date.rs
third_party/rust/headers/src/common/etag.rs
third_party/rust/headers/src/common/expect.rs
third_party/rust/headers/src/common/expires.rs
third_party/rust/headers/src/common/host.rs
third_party/rust/headers/src/common/if_match.rs
third_party/rust/headers/src/common/if_modified_since.rs
third_party/rust/headers/src/common/if_none_match.rs
third_party/rust/headers/src/common/if_range.rs
third_party/rust/headers/src/common/if_unmodified_since.rs
third_party/rust/headers/src/common/last_modified.rs
third_party/rust/headers/src/common/location.rs
third_party/rust/headers/src/common/mod.rs
third_party/rust/headers/src/common/origin.rs
third_party/rust/headers/src/common/pragma.rs
third_party/rust/headers/src/common/proxy_authorization.rs
third_party/rust/headers/src/common/range.rs
third_party/rust/headers/src/common/referer.rs
third_party/rust/headers/src/common/referrer_policy.rs
third_party/rust/headers/src/common/retry_after.rs
third_party/rust/headers/src/common/sec_websocket_accept.rs
third_party/rust/headers/src/common/sec_websocket_key.rs
third_party/rust/headers/src/common/sec_websocket_version.rs
third_party/rust/headers/src/common/server.rs
third_party/rust/headers/src/common/set_cookie.rs
third_party/rust/headers/src/common/strict_transport_security.rs
third_party/rust/headers/src/common/te.rs
third_party/rust/headers/src/common/transfer_encoding.rs
third_party/rust/headers/src/common/upgrade.rs
third_party/rust/headers/src/common/user_agent.rs
third_party/rust/headers/src/common/vary.rs
third_party/rust/headers/src/disabled/accept.rs
third_party/rust/headers/src/disabled/accept_charset.rs
third_party/rust/headers/src/disabled/accept_encoding.rs
third_party/rust/headers/src/disabled/accept_language.rs
third_party/rust/headers/src/disabled/content_language.rs
third_party/rust/headers/src/disabled/from.rs
third_party/rust/headers/src/disabled/last_event_id.rs
third_party/rust/headers/src/disabled/link.rs
third_party/rust/headers/src/disabled/prefer.rs
third_party/rust/headers/src/disabled/preference_applied.rs
third_party/rust/headers/src/disabled/util/charset.rs
third_party/rust/headers/src/disabled/util/encoding.rs
third_party/rust/headers/src/disabled/util/extended_value.rs
third_party/rust/headers/src/disabled/util/quality_value.rs
third_party/rust/headers/src/disabled/warning.rs
third_party/rust/headers/src/lib.rs
third_party/rust/headers/src/map_ext.rs
third_party/rust/headers/src/util/csv.rs
third_party/rust/headers/src/util/entity.rs
third_party/rust/headers/src/util/flat_csv.rs
third_party/rust/headers/src/util/fmt.rs
third_party/rust/headers/src/util/http_date.rs
third_party/rust/headers/src/util/iter.rs
third_party/rust/headers/src/util/mod.rs
third_party/rust/headers/src/util/seconds.rs
third_party/rust/headers/src/util/value_string.rs
third_party/rust/http/.cargo-checksum.json
third_party/rust/http/CHANGELOG.md
third_party/rust/http/Cargo.toml
third_party/rust/http/README.md
third_party/rust/http/benches/uri.rs
third_party/rust/http/src/byte_str.rs
third_party/rust/http/src/convert.rs
third_party/rust/http/src/error.rs
third_party/rust/http/src/header/map.rs
third_party/rust/http/src/header/mod.rs
third_party/rust/http/src/header/name.rs
third_party/rust/http/src/header/value.rs
third_party/rust/http/src/lib.rs
third_party/rust/http/src/method.rs
third_party/rust/http/src/request.rs
third_party/rust/http/src/response.rs
third_party/rust/http/src/status.rs
third_party/rust/http/src/uri/authority.rs
third_party/rust/http/src/uri/builder.rs
third_party/rust/http/src/uri/mod.rs
third_party/rust/http/src/uri/path.rs
third_party/rust/http/src/uri/port.rs
third_party/rust/http/src/uri/scheme.rs
third_party/rust/http/src/uri/tests.rs
third_party/rust/http/tests/header_map.rs
third_party/rust/hyper/.cargo-checksum.json
third_party/rust/hyper/Cargo.toml
third_party/rust/hyper/LICENSE
third_party/rust/hyper/src/body/chunk.rs
third_party/rust/hyper/src/client/conn.rs
third_party/rust/hyper/src/client/connect.rs
third_party/rust/hyper/src/client/connect/dns.rs
third_party/rust/hyper/src/client/connect/http.rs
third_party/rust/hyper/src/client/connect/mod.rs
third_party/rust/hyper/src/client/dns.rs
third_party/rust/hyper/src/client/mod.rs
third_party/rust/hyper/src/client/pool.rs
third_party/rust/hyper/src/client/tests.rs
third_party/rust/hyper/src/common/drain.rs
third_party/rust/hyper/src/common/exec.rs
third_party/rust/hyper/src/common/lazy.rs
third_party/rust/hyper/src/common/mod.rs
third_party/rust/hyper/src/error.rs
third_party/rust/hyper/src/headers.rs
third_party/rust/hyper/src/lib.rs
third_party/rust/hyper/src/mock.rs
third_party/rust/hyper/src/proto/h1/conn.rs
third_party/rust/hyper/src/proto/h1/date.rs
third_party/rust/hyper/src/proto/h1/dispatch.rs
third_party/rust/hyper/src/proto/h1/io.rs
third_party/rust/hyper/src/proto/h1/mod.rs
third_party/rust/hyper/src/proto/h1/role.rs
third_party/rust/hyper/src/proto/h2/client.rs
third_party/rust/hyper/src/proto/h2/mod.rs
third_party/rust/hyper/src/proto/h2/server.rs
third_party/rust/hyper/src/server/conn.rs
third_party/rust/hyper/src/server/mod.rs
third_party/rust/hyper/src/server/shutdown.rs
third_party/rust/hyper/src/server/tcp.rs
third_party/rust/hyper/src/service/make_service.rs
third_party/rust/hyper/src/service/mod.rs
third_party/rust/hyper/src/service/new_service.rs
third_party/rust/input_buffer/.cargo-checksum.json
third_party/rust/input_buffer/Cargo.toml
third_party/rust/input_buffer/LICENSE-APACHE
third_party/rust/input_buffer/LICENSE-MIT
third_party/rust/input_buffer/README.md
third_party/rust/input_buffer/src/lib.rs
third_party/rust/mime/.cargo-checksum.json
third_party/rust/mime/CONTRIBUTING.md
third_party/rust/mime/Cargo.toml
third_party/rust/mime/LICENSE-APACHE
third_party/rust/mime/LICENSE-MIT
third_party/rust/mime/README.md
third_party/rust/mime/benches/cmp.rs
third_party/rust/mime/benches/fmt.rs
third_party/rust/mime/benches/parse.rs
third_party/rust/mime/src/lib.rs
third_party/rust/mime/src/parse.rs
third_party/rust/mime_guess/.cargo-checksum.json
third_party/rust/mime_guess/Cargo.toml
third_party/rust/mime_guess/LICENSE
third_party/rust/mime_guess/README.md
third_party/rust/mime_guess/build.rs
third_party/rust/mime_guess/examples/rev_map.rs
third_party/rust/mime_guess/src/lib.rs
third_party/rust/mime_guess/src/mime_types.rs
third_party/rust/mio-uds/.cargo-checksum.json
third_party/rust/mio-uds/Cargo.toml
third_party/rust/mio-uds/README.md
third_party/rust/mio-uds/src/lib.rs
third_party/rust/mio-uds/src/listener.rs
third_party/rust/mio-uds/src/socket.rs
third_party/rust/mio-uds/src/stream.rs
third_party/rust/mio-uds/tests/smoke.rs
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/scoped-tls/.cargo-checksum.json
third_party/rust/scoped-tls/Cargo.toml
third_party/rust/scoped-tls/README.md
third_party/rust/scoped-tls/src/lib.rs
third_party/rust/serde_urlencoded/.cargo-checksum.json
third_party/rust/serde_urlencoded/Cargo.toml
third_party/rust/serde_urlencoded/LICENSE-APACHE
third_party/rust/serde_urlencoded/LICENSE-MIT
third_party/rust/serde_urlencoded/README.md
third_party/rust/serde_urlencoded/bors.toml
third_party/rust/serde_urlencoded/rustfmt.toml
third_party/rust/serde_urlencoded/src/de.rs
third_party/rust/serde_urlencoded/src/lib.rs
third_party/rust/serde_urlencoded/src/ser/key.rs
third_party/rust/serde_urlencoded/src/ser/mod.rs
third_party/rust/serde_urlencoded/src/ser/pair.rs
third_party/rust/serde_urlencoded/src/ser/part.rs
third_party/rust/serde_urlencoded/src/ser/value.rs
third_party/rust/serde_urlencoded/tests/test_deserialize.rs
third_party/rust/serde_urlencoded/tests/test_serialize.rs
third_party/rust/tokio-current-thread/.cargo-checksum.json
third_party/rust/tokio-current-thread/CHANGELOG.md
third_party/rust/tokio-current-thread/Cargo.toml
third_party/rust/tokio-current-thread/LICENSE
third_party/rust/tokio-current-thread/README.md
third_party/rust/tokio-current-thread/src/lib.rs
third_party/rust/tokio-current-thread/src/scheduler.rs
third_party/rust/tokio-current-thread/tests/current_thread.rs
third_party/rust/tokio-executor/.cargo-checksum.json
third_party/rust/tokio-executor/CHANGELOG.md
third_party/rust/tokio-executor/Cargo.toml
third_party/rust/tokio-executor/LICENSE
third_party/rust/tokio-executor/README.md
third_party/rust/tokio-executor/src/enter.rs
third_party/rust/tokio-executor/src/error.rs
third_party/rust/tokio-executor/src/executor.rs
third_party/rust/tokio-executor/src/global.rs
third_party/rust/tokio-executor/src/lib.rs
third_party/rust/tokio-executor/src/park.rs
third_party/rust/tokio-executor/src/typed.rs
third_party/rust/tokio-executor/tests/executor.rs
third_party/rust/tokio-threadpool/.cargo-checksum.json
third_party/rust/tokio-threadpool/CHANGELOG.md
third_party/rust/tokio-threadpool/Cargo.toml
third_party/rust/tokio-threadpool/LICENSE
third_party/rust/tokio-threadpool/README.md
third_party/rust/tokio-threadpool/examples/smoke.rs
third_party/rust/tokio-threadpool/src/blocking.rs
third_party/rust/tokio-threadpool/src/builder.rs
third_party/rust/tokio-threadpool/src/futures2_wake.rs
third_party/rust/tokio-threadpool/src/lib.rs
third_party/rust/tokio-threadpool/src/notifier.rs
third_party/rust/tokio-threadpool/src/park/default_park.rs
third_party/rust/tokio-threadpool/src/pool/backup.rs
third_party/rust/tokio-threadpool/src/pool/backup_stack.rs
third_party/rust/tokio-threadpool/src/pool/mod.rs
third_party/rust/tokio-threadpool/src/sender.rs
third_party/rust/tokio-threadpool/src/shutdown.rs
third_party/rust/tokio-threadpool/src/shutdown_task.rs
third_party/rust/tokio-threadpool/src/task/blocking.rs
third_party/rust/tokio-threadpool/src/task/mod.rs
third_party/rust/tokio-threadpool/src/task/queue.rs
third_party/rust/tokio-threadpool/src/thread_pool.rs
third_party/rust/tokio-threadpool/src/worker/entry.rs
third_party/rust/tokio-threadpool/src/worker/mod.rs
third_party/rust/tokio-threadpool/src/worker/stack.rs
third_party/rust/tokio-threadpool/tests/blocking.rs
third_party/rust/tokio-threadpool/tests/threadpool.rs
third_party/rust/tokio-timer/.cargo-checksum.json
third_party/rust/tokio-timer/CHANGELOG.md
third_party/rust/tokio-timer/Cargo.toml
third_party/rust/tokio-timer/LICENSE
third_party/rust/tokio-timer/README.md
third_party/rust/tokio-timer/src/atomic.rs
third_party/rust/tokio-timer/src/clock/clock.rs
third_party/rust/tokio-timer/src/clock/mod.rs
third_party/rust/tokio-timer/src/clock/now.rs
third_party/rust/tokio-timer/src/deadline.rs
third_party/rust/tokio-timer/src/delay.rs
third_party/rust/tokio-timer/src/delay_queue.rs
third_party/rust/tokio-timer/src/interval.rs
third_party/rust/tokio-timer/src/lib.rs
third_party/rust/tokio-timer/src/throttle.rs
third_party/rust/tokio-timer/src/timeout.rs
third_party/rust/tokio-timer/src/timer/atomic_stack.rs
third_party/rust/tokio-timer/src/timer/entry.rs
third_party/rust/tokio-timer/src/timer/handle.rs
third_party/rust/tokio-timer/src/timer/level.rs
third_party/rust/tokio-timer/src/timer/mod.rs
third_party/rust/tokio-timer/src/timer/now.rs
third_party/rust/tokio-timer/src/timer/registration.rs
third_party/rust/tokio-timer/src/timer/stack.rs
third_party/rust/tokio-timer/src/wheel/level.rs
third_party/rust/tokio-timer/src/wheel/mod.rs
third_party/rust/tokio-timer/src/wheel/stack.rs
third_party/rust/tokio-timer/tests/deadline.rs
third_party/rust/tokio-timer/tests/delay.rs
third_party/rust/tokio-timer/tests/hammer.rs
third_party/rust/tokio-timer/tests/interval.rs
third_party/rust/tokio-timer/tests/queue.rs
third_party/rust/tokio-timer/tests/support/mod.rs
third_party/rust/tokio-timer/tests/throttle.rs
third_party/rust/tokio-timer/tests/timeout.rs
third_party/rust/tokio-uds-0.1.7/.cargo-checksum.json
third_party/rust/tokio-uds-0.1.7/Cargo.toml
third_party/rust/tokio-uds-0.1.7/LICENSE-APACHE
third_party/rust/tokio-uds-0.1.7/LICENSE-MIT
third_party/rust/tokio-uds-0.1.7/README.md
third_party/rust/tokio-uds-0.1.7/src/frame.rs
third_party/rust/tokio-uds-0.1.7/src/lib.rs
third_party/rust/tokio-uds-0.1.7/src/ucred.rs
third_party/rust/tokio-uds/.cargo-checksum.json
third_party/rust/tokio-uds/CHANGELOG.md
third_party/rust/tokio-uds/Cargo.toml
third_party/rust/tokio-uds/LICENSE
third_party/rust/tokio-uds/LICENSE-APACHE
third_party/rust/tokio-uds/LICENSE-MIT
third_party/rust/tokio-uds/README.md
third_party/rust/tokio-uds/src/datagram.rs
third_party/rust/tokio-uds/src/frame.rs
third_party/rust/tokio-uds/src/incoming.rs
third_party/rust/tokio-uds/src/lib.rs
third_party/rust/tokio-uds/src/listener.rs
third_party/rust/tokio-uds/src/recv_dgram.rs
third_party/rust/tokio-uds/src/send_dgram.rs
third_party/rust/tokio-uds/src/stream.rs
third_party/rust/tokio-uds/src/ucred.rs
third_party/rust/tokio-uds/tests/datagram.rs
third_party/rust/tokio-uds/tests/stream.rs
third_party/rust/tokio/.cargo-checksum.json
third_party/rust/tokio/CHANGELOG.md
third_party/rust/tokio/CONTRIBUTING.md
third_party/rust/tokio/Cargo.toml
third_party/rust/tokio/README.md
third_party/rust/tokio/benches/tcp.rs
third_party/rust/tokio/ci/tsan
third_party/rust/tokio/examples/chat.rs
third_party/rust/tokio/examples/connect.rs
third_party/rust/tokio/examples/echo-udp.rs
third_party/rust/tokio/examples/manual-runtime.rs
third_party/rust/tokio/examples/print_each_packet.rs
third_party/rust/tokio/examples/tinydb.rs
third_party/rust/tokio/examples/tinyhttp.rs
third_party/rust/tokio/src/async_await.rs
third_party/rust/tokio/src/clock.rs
third_party/rust/tokio/src/codec/length_delimited.rs
third_party/rust/tokio/src/codec/mod.rs
third_party/rust/tokio/src/executor/current_thread/mod.rs
third_party/rust/tokio/src/executor/current_thread/scheduler.rs
third_party/rust/tokio/src/executor/mod.rs
third_party/rust/tokio/src/fs.rs
third_party/rust/tokio/src/io.rs
third_party/rust/tokio/src/lib.rs
third_party/rust/tokio/src/net.rs
third_party/rust/tokio/src/prelude.rs
third_party/rust/tokio/src/reactor/mod.rs
third_party/rust/tokio/src/runtime/builder.rs
third_party/rust/tokio/src/runtime/current_thread/mod.rs
third_party/rust/tokio/src/runtime/current_thread/runtime.rs
third_party/rust/tokio/src/runtime/mod.rs
third_party/rust/tokio/src/runtime/task_executor.rs
third_party/rust/tokio/src/timer.rs
third_party/rust/tokio/src/util/future.rs
third_party/rust/tokio/src/util/mod.rs
third_party/rust/tokio/src/util/stream.rs
third_party/rust/tokio/tests/buffered.rs
third_party/rust/tokio/tests/clock.rs
third_party/rust/tokio/tests/current_thread.rs
third_party/rust/tokio/tests/echo2.rs
third_party/rust/tokio/tests/global.rs
third_party/rust/tokio/tests/global2.rs
third_party/rust/tokio/tests/length_delimited.rs
third_party/rust/tokio/tests/line-frames.rs
third_party/rust/tokio/tests/pipe-hup.rs
third_party/rust/tokio/tests/reactor.rs
third_party/rust/tokio/tests/runtime.rs
third_party/rust/tokio/tests/tcp2.rs
third_party/rust/tokio/tests/timer.rs
third_party/rust/tungstenite/.cargo-checksum.json
third_party/rust/tungstenite/Cargo.toml
third_party/rust/tungstenite/LICENSE-APACHE
third_party/rust/tungstenite/LICENSE-MIT
third_party/rust/tungstenite/README.md
third_party/rust/tungstenite/autobahn/client-results.json
third_party/rust/tungstenite/autobahn/fuzzingclient.json
third_party/rust/tungstenite/autobahn/fuzzingserver.json
third_party/rust/tungstenite/autobahn/server-results.json
third_party/rust/tungstenite/examples/autobahn-client.rs
third_party/rust/tungstenite/examples/autobahn-server.rs
third_party/rust/tungstenite/examples/callback-error.rs
third_party/rust/tungstenite/examples/client.rs
third_party/rust/tungstenite/examples/server.rs
third_party/rust/tungstenite/scripts/autobahn-client.sh
third_party/rust/tungstenite/scripts/autobahn-server.sh
third_party/rust/tungstenite/src/client.rs
third_party/rust/tungstenite/src/error.rs
third_party/rust/tungstenite/src/handshake/client.rs
third_party/rust/tungstenite/src/handshake/headers.rs
third_party/rust/tungstenite/src/handshake/machine.rs
third_party/rust/tungstenite/src/handshake/mod.rs
third_party/rust/tungstenite/src/handshake/server.rs
third_party/rust/tungstenite/src/lib.rs
third_party/rust/tungstenite/src/protocol/frame/coding.rs
third_party/rust/tungstenite/src/protocol/frame/frame.rs
third_party/rust/tungstenite/src/protocol/frame/mask.rs
third_party/rust/tungstenite/src/protocol/frame/mod.rs
third_party/rust/tungstenite/src/protocol/message.rs
third_party/rust/tungstenite/src/protocol/mod.rs
third_party/rust/tungstenite/src/server.rs
third_party/rust/tungstenite/src/stream.rs
third_party/rust/tungstenite/src/util.rs
third_party/rust/unicase-1.4.2/.cargo-checksum.json
third_party/rust/unicase-1.4.2/Cargo.toml
third_party/rust/unicase-1.4.2/LICENSE
third_party/rust/unicase-1.4.2/README.md
third_party/rust/unicase-1.4.2/build.rs
third_party/rust/unicase-1.4.2/src/lib.rs
third_party/rust/unicase/.cargo-checksum.json
third_party/rust/unicase/Cargo.toml
third_party/rust/unicase/LICENSE-APACHE
third_party/rust/unicase/LICENSE-MIT
third_party/rust/unicase/README.md
third_party/rust/unicase/build.rs
third_party/rust/unicase/src/ascii.rs
third_party/rust/unicase/src/lib.rs
third_party/rust/unicase/src/unicode/map.rs
third_party/rust/unicase/src/unicode/mod.rs
third_party/rust/urlencoding/.cargo-checksum.json
third_party/rust/urlencoding/Cargo.toml
third_party/rust/urlencoding/LICENSE
third_party/rust/urlencoding/README.md
third_party/rust/urlencoding/src/lib.rs
third_party/rust/utf-8/.cargo-checksum.json
third_party/rust/utf-8/Cargo.toml
third_party/rust/utf-8/README.md
third_party/rust/utf-8/benches/from_utf8_lossy.rs
third_party/rust/utf-8/src/lib.rs
third_party/rust/utf-8/src/lossy.rs
third_party/rust/utf-8/src/read.rs
third_party/rust/utf-8/tests/unit.rs
third_party/rust/version_check/.cargo-checksum.json
third_party/rust/version_check/Cargo.toml
third_party/rust/version_check/LICENSE-APACHE
third_party/rust/version_check/LICENSE-MIT
third_party/rust/version_check/README.md
third_party/rust/version_check/src/lib.rs
third_party/rust/warp/.cargo-checksum.json
third_party/rust/warp/CHANGELOG.md
third_party/rust/warp/Cargo.toml
third_party/rust/warp/LICENSE
third_party/rust/warp/README.md
third_party/rust/warp/examples/body.rs
third_party/rust/warp/examples/dir.rs
third_party/rust/warp/examples/dir/another.html
third_party/rust/warp/examples/dir/index.html
third_party/rust/warp/examples/errors.rs
third_party/rust/warp/examples/file.rs
third_party/rust/warp/examples/futures.rs
third_party/rust/warp/examples/handlebars_template.rs
third_party/rust/warp/examples/headers.rs
third_party/rust/warp/examples/hello.rs
third_party/rust/warp/examples/returning.rs
third_party/rust/warp/examples/routing.rs
third_party/rust/warp/examples/sse.rs
third_party/rust/warp/examples/sse_chat.rs
third_party/rust/warp/examples/tls.rs
third_party/rust/warp/examples/tls/cert.pem
third_party/rust/warp/examples/tls/key.rsa
third_party/rust/warp/examples/todos.rs
third_party/rust/warp/examples/websockets.rs
third_party/rust/warp/examples/websockets_chat.rs
third_party/rust/warp/src/error.rs
third_party/rust/warp/src/filter/and.rs
third_party/rust/warp/src/filter/and_then.rs
third_party/rust/warp/src/filter/boxed.rs
third_party/rust/warp/src/filter/map.rs
third_party/rust/warp/src/filter/map_err.rs
third_party/rust/warp/src/filter/mod.rs
third_party/rust/warp/src/filter/or.rs
third_party/rust/warp/src/filter/or_else.rs
third_party/rust/warp/src/filter/recover.rs
third_party/rust/warp/src/filter/service.rs
third_party/rust/warp/src/filter/unify.rs
third_party/rust/warp/src/filter/untuple_one.rs
third_party/rust/warp/src/filter/wrap.rs
third_party/rust/warp/src/filters/addr.rs
third_party/rust/warp/src/filters/any.rs
third_party/rust/warp/src/filters/body.rs
third_party/rust/warp/src/filters/cookie.rs
third_party/rust/warp/src/filters/cors.rs
third_party/rust/warp/src/filters/ext.rs
third_party/rust/warp/src/filters/fs.rs
third_party/rust/warp/src/filters/header.rs
third_party/rust/warp/src/filters/log.rs
third_party/rust/warp/src/filters/method.rs
third_party/rust/warp/src/filters/mod.rs
third_party/rust/warp/src/filters/path.rs
third_party/rust/warp/src/filters/query.rs
third_party/rust/warp/src/filters/reply.rs
third_party/rust/warp/src/filters/sse.rs
third_party/rust/warp/src/filters/ws.rs
third_party/rust/warp/src/generic.rs
third_party/rust/warp/src/lib.rs
third_party/rust/warp/src/never.rs
third_party/rust/warp/src/redirect.rs
third_party/rust/warp/src/reject.rs
third_party/rust/warp/src/reply.rs
third_party/rust/warp/src/route.rs
third_party/rust/warp/src/server.rs
third_party/rust/warp/src/test.rs
third_party/rust/warp/src/tls.rs
third_party/rust/warp/src/transport.rs
third_party/rust/warp/tests/body.rs
third_party/rust/warp/tests/cookie.rs
third_party/rust/warp/tests/cors.rs
third_party/rust/warp/tests/ext.rs
third_party/rust/warp/tests/filter.rs
third_party/rust/warp/tests/fs.rs
third_party/rust/warp/tests/header.rs
third_party/rust/warp/tests/method.rs
third_party/rust/warp/tests/path.rs
third_party/rust/warp/tests/query.rs
third_party/rust/warp/tests/redirect.rs
third_party/rust/warp/tests/reply_with.rs
third_party/rust/warp/tests/ws.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crossbeam-channel/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{"CHANGELOG.md":"615aff5b524bbefd40063255084cc644e3ae37e043799b28ff55e67bfd2b3dc4","Cargo.toml":"fce8c5285af6e361f694dd00bda2d6162e9f896c60b7f81c206b7eb769728726","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","LICENSE-THIRD-PARTY":"924a49392dc8304def57586be4ebd69aaf51e16fd245b55b4b69ad2cce6b715a","README.md":"077c5ddbd471d4a21f5b183e415b708e5100fcad8baed335fd4ad5b6f959a8be","examples/fibonacci.rs":"8755bcb9cf05e391d8679fbb51db40ed9692703c3b66341cd1c1e4cca2068874","examples/matching.rs":"1fd35488bf42e1782a339b9691a4e82dcf23ad12502809e33555d46c91739476","examples/stopwatch.rs":"4e90ce134475859a421da0a095baea52a575b03e41fb8fb50cf47446f422ee6e","src/channel.rs":"4d398567823e2e8189de91d67ef58e4b61d1b8d3f1e373da2664ed40ae154717","src/context.rs":"5c57679e0d3d63f2df11c7b74c70b5d97a6c2e50a6b2fcd60f1f077d59b88598","src/counter.rs":"3a9c1b0fa94beeabd349789ca94453f0cb3aa67f5d56bc619a7e029956fd3dbf","src/err.rs":"1a9ac9d7f4d5561f9c3e513b2f776782783954efa0bf9428598f3ad9ccb9d5c9","src/flavors/after.rs":"4f761618efe21036145e44f01506bdfbc2524879368ac138600e0feed921a6a7","src/flavors/array.rs":"be4f7a50acef56b170f288df30722d69fd9388496c8a6bb480d0322ead6d79c4","src/flavors/list.rs":"e9c615aa0f04e222a01dfa6edc9cd1a83036d924db999480f83baa1123779d07","src/flavors/mod.rs":"a5af9b6105207e293c0d64928b4486fb1da9bfe0318354c66c8b5069e41ec31f","src/flavors/never.rs":"86e21b4d8b154e5d795cf72c7203a1d16a846c4d670095c8b592c12569f35a98","src/flavors/tick.rs":"3ae19df71310972e7b5fd8cac17d90bff683e1493ed3db26d0d3d329dff133ff","src/flavors/zero.rs":"cae6eb914d36e58810704d7200b1dc90ff6cc03b23a97fa3ac04fbd00f18381a","src/lib.rs":"bc843b55c65d3a20ad1fc56da675e48232af5373339f2e513b4f6d4460e0000d","src/select.rs":"99797f44c141eea8a1a64cd6fef629812680f6ec3393da1bb7e4b3a701028ec6","src/select_macro.rs":"e8f3998ab86f54e46acaa48bd6bba9b2e955ed11710d23c46f256295575fd638","src/utils.rs":"ebf230fed429c353f6202fe10c33dcca69a0917a947665a7ee03d230b88a29bf","src/waker.rs":"e85114e43a4db4befadd79b574c2567f3076e460791c2ea6b9588ee824d2c988","tests/after.rs":"9336716edbb6e3145f006e62af59a4e82160ecfb8748fac174b844fb81442d45","tests/array.rs":"1e87f8e2e75dcbaf0dbc75394cfa329c0fd5719db0bdb9ba2aa0cc86b2a18044","tests/golang.rs":"08c13a4fafd25da03809f20965203e4e88bdf936ff53342f2e43430e6603d3fa","tests/iter.rs":"3beaac492a9df39d2eae31d7cdb88f4ee3bd3cb57e2c5c9705811b8ee2abe744","tests/list.rs":"0a664517f3ff49e0885f6c649cbc76f5e5c7a4940096d7a1c98728cbe1655948","tests/mpsc.rs":"d268beb7bcb0be864bdb745585979c97343b82761705907fd90b0ec85f2db7d4","tests/never.rs":"cd455a4c78403d9a96fe0f3a4e968164cca533cc85c96aaa4558987f9b088fcc","tests/ready.rs":"7bc0dd86cd987dcae7db84c9f4379a2421e088b4e5dbdc07affb10c853fc7f55","tests/select.rs":"1ace0bbd2aecf488827d2c16d5d32b47baf00b0a1f7f7470bf9c8e16ddf92dad","tests/select_macro.rs":"d303abb0a3f7ff9bb3b5253951d7d17bfb30e4f77fb66d11c40a063691f9a9ae","tests/thread_locals.rs":"e9d25086d4bc590bacdaf20b5ff0ff3741d3403a413a8b817eaf15f61fb5e644","tests/tick.rs":"011c39a85f1e0427e61e7afc0860cf6dc29d41f7e8be9709684e4ffdc26ef9b8","tests/zero.rs":"983998a52173fba22045fb8390566a59ebb0392834477ab94cac934d637a3231"},"package":"8d4f5844607ce8da3fff431e7dba56cda8bfcc570aa50bee36adba8a32b8cad7"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crossbeam-channel/CHANGELOG.md
@@ -0,0 +1,133 @@
+# Version 0.3.7
+
+- Remove `parking_lot` and `rand` dependencies.
+- Expand documentation.
+- Implement `Default` for `Select`.
+- Make `size_of::<Receiver<T>>()` smaller.
+- Several minor optimizations.
+- Add more tests.
+
+# Version 0.3.6
+
+- Fix a bug in initialization of unbounded channels.
+
+# Version 0.3.5
+
+- New implementation for unbounded channels.
+- A number of small performance improvements.
+- Remove `crossbeam-epoch` dependency.
+
+# Version 0.3.4
+
+- Bump `crossbeam-epoch` to `0.7`.
+- Improve documentation.
+
+# Version 0.3.3
+
+- Relax the lifetime in `SelectedOperation<'_>`.
+- Add `Select::try_ready()`, `Select::ready()`, and `Select::ready_timeout()`.
+- Update licensing notices.
+- Improve documentation.
+- Add methods `is_disconnected()`, `is_timeout()`, `is_empty()`, and `is_full()` on error types.
+
+# Version 0.3.2
+
+- More elaborate licensing notices.
+
+# Version 0.3.1
+
+- Update `crossbeam-utils` to `0.6`.
+
+# Version 0.3.0
+
+- Add a special `never` channel type.
+- Dropping all receivers now closes the channel.
+- The interface of sending and receiving methods is now very similar to those in v0.1.
+- The syntax for `send` in `select!` is now `send(sender, msg) -> res => body`.
+- The syntax for `recv` in `select!` is now `recv(receiver) -> res => body`.
+- New, more efficient interface for `Select` without callbacks.
+- Timeouts can be specified in `select!`.
+
+# Version 0.2.6
+
+- `Select` struct that can add cases dynamically.
+- More documentation (in particular, the FAQ section).
+- Optimize contended sends/receives in unbounded channels.
+
+# Version 0.2.5
+
+- Use `LocalKey::try_with` instead of `LocalKey::with`.
+- Remove helper macros `__crossbeam_channel*`.
+
+# Version 0.2.4
+
+- Make `select!` linearizable with other channel operations.
+- Update `crossbeam-utils` to `0.5.0`.
+- Update `parking_lot` to `0.6.3`.
+- Remove Mac OS X tests.
+
+# Version 0.2.3
+
+- Add Mac OS X tests.
+- Lower some memory orderings.
+- Eliminate calls to `mem::unitialized`, which caused bugs with ZST.
+
+# Version 0.2.2
+
+- Add more tests.
+- Update `crossbeam-epoch` to 0.5.0
+- Initialize the RNG seed to a random value.
+- Replace `libc::abort` with `std::process::abort`.
+- Ignore clippy warnings in `select!`.
+- Better interaction of `select!` with the NLL borrow checker.
+
+# Version 0.2.1
+
+- Fix compilation errors when using `select!` with `#[deny(unsafe_code)]`.
+
+# Version 0.2.0
+
+- Implement `IntoIterator<Item = T>` for `Receiver<T>`.
+- Add a new `select!` macro.
+- Add special channels `after` and `tick`.
+- Dropping receivers doesn't close the channel anymore.
+- Change the signature of `recv`, `send`, and `try_recv`.
+- Remove `Sender::is_closed` and `Receiver::is_closed`.
+- Remove `Sender::close` and `Receiver::close`.
+- Remove `Sender::send_timeout` and `Receiver::recv_timeout`.
+- Remove `Sender::try_send`.
+- Remove `Select` and `select_loop!`.
+- Remove all error types.
+- Remove `Iter`, `TryIter`, and `IntoIter`.
+- Remove the `nightly` feature.
+- Remove ordering operators for `Sender` and `Receiver`.
+
+# Version 0.1.3
+
+- Add `Sender::disconnect` and `Receiver::disconnect`.
+- Implement comparison operators for `Sender` and `Receiver`.
+- Allow arbitrary patterns in place of `msg` in `recv(r, msg)`.
+- Add a few conversion impls between error types.
+- Add benchmarks for `atomicring` and `mpmc`.
+- Add benchmarks for different message sizes.
+- Documentation improvements.
+- Update `crossbeam-epoch` to 0.4.0
+- Update `crossbeam-utils` to 0.3.0
+- Update `parking_lot` to 0.5
+- Update `rand` to 0.4
+
+# Version 0.1.2
+
+- Allow conditional cases in `select_loop!` macro.
+- Fix typos in documentation.
+- Fix deadlock in selection when all channels are disconnected and a timeout is specified.
+
+# Version 0.1.1
+
+- Implement `Debug` for `Sender`, `Receiver`, `Iter`, `TryIter`, `IntoIter`, and `Select`.
+- Implement `Default` for `Select`.
+
+# Version 0.1.0
+
+- First implementation of the channels.
+- Add `select_loop!` macro by @TimNN.
rename from third_party/rust/crossbeam-utils-0.3.2/Cargo.toml
rename to third_party/rust/crossbeam-channel/Cargo.toml
--- a/third_party/rust/crossbeam-utils-0.3.2/Cargo.toml
+++ b/third_party/rust/crossbeam-channel/Cargo.toml
@@ -6,26 +6,29 @@
 # 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 = "crossbeam-utils"
-version = "0.3.2"
+name = "crossbeam-channel"
+version = "0.3.7"
 authors = ["The Crossbeam Project Developers"]
-description = "Utilities for concurrent programming"
-homepage = "https://github.com/crossbeam-rs/crossbeam-utils"
-documentation = "https://docs.rs/crossbeam-utils"
+description = "Multi-producer multi-consumer channels for message passing"
+homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-channel"
+documentation = "https://docs.rs/crossbeam-channel"
 readme = "README.md"
-keywords = ["scoped", "thread", "atomic", "cache"]
+keywords = ["channel", "mpmc", "select", "golang", "message"]
 categories = ["algorithms", "concurrency", "data-structures"]
 license = "MIT/Apache-2.0"
-repository = "https://github.com/crossbeam-rs/crossbeam-utils"
-[dependencies.cfg-if]
-version = "0.1"
+repository = "https://github.com/crossbeam-rs/crossbeam"
+[dependencies.crossbeam-utils]
+version = "0.6"
 
-[features]
-default = ["use_std"]
-nightly = []
-use_std = []
+[dependencies.smallvec]
+version = "0.6.2"
+[dev-dependencies.rand]
+version = "0.6"
+
+[dev-dependencies.signal-hook]
+version = "0.1.5"
rename from third_party/rust/crossbeam-utils-0.3.2/LICENSE-APACHE
rename to third_party/rust/crossbeam-channel/LICENSE-APACHE
rename from third_party/rust/tokio-uds/LICENSE-MIT
rename to third_party/rust/crossbeam-channel/LICENSE-MIT
--- a/third_party/rust/tokio-uds/LICENSE-MIT
+++ b/third_party/rust/crossbeam-channel/LICENSE-MIT
@@ -1,10 +1,8 @@
-Copyright (c) 2016 Alex Crichton
-
 Permission is hereby granted, free of charge, to any
 person obtaining a copy of this software and associated
 documentation files (the "Software"), to deal in the
 Software without restriction, including without
 limitation the rights to use, copy, modify, merge,
 publish, distribute, sublicense, and/or sell copies of
 the Software, and to permit persons to whom the Software
 is furnished to do so, subject to the following
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crossbeam-channel/LICENSE-THIRD-PARTY
@@ -0,0 +1,625 @@
+===============================================================================
+
+Bounded MPMC queue
+http://www.1024cores.net/home/code-license
+
+Copyright (c) 2010-2011 Dmitry Vyukov.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The views and conclusions contained in the software and documentation are those
+of the authors and should not be interpreted as representing official policies,
+either expressed or implied, of Dmitry Vyukov.
+
+===============================================================================
+
+matching.go
+https://creativecommons.org/licenses/by/3.0/legalcode
+
+Creative Commons Legal Code
+
+Attribution 3.0 Unported
+
+    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+    LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
+    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+    INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+    REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
+    DAMAGES RESULTING FROM ITS USE.
+
+License
+
+THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
+COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
+COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
+AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+
+BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
+TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
+BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
+CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
+CONDITIONS.
+
+1. Definitions
+
+ a. "Adaptation" means a work based upon the Work, or upon the Work and
+    other pre-existing works, such as a translation, adaptation,
+    derivative work, arrangement of music or other alterations of a
+    literary or artistic work, or phonogram or performance and includes
+    cinematographic adaptations or any other form in which the Work may be
+    recast, transformed, or adapted including in any form recognizably
+    derived from the original, except that a work that constitutes a
+    Collection will not be considered an Adaptation for the purpose of
+    this License. For the avoidance of doubt, where the Work is a musical
+    work, performance or phonogram, the synchronization of the Work in
+    timed-relation with a moving image ("synching") will be considered an
+    Adaptation for the purpose of this License.
+ b. "Collection" means a collection of literary or artistic works, such as
+    encyclopedias and anthologies, or performances, phonograms or
+    broadcasts, or other works or subject matter other than works listed
+    in Section 1(f) below, which, by reason of the selection and
+    arrangement of their contents, constitute intellectual creations, in
+    which the Work is included in its entirety in unmodified form along
+    with one or more other contributions, each constituting separate and
+    independent works in themselves, which together are assembled into a
+    collective whole. A work that constitutes a Collection will not be
+    considered an Adaptation (as defined above) for the purposes of this
+    License.
+ c. "Distribute" means to make available to the public the original and
+    copies of the Work or Adaptation, as appropriate, through sale or
+    other transfer of ownership.
+ d. "Licensor" means the individual, individuals, entity or entities that
+    offer(s) the Work under the terms of this License.
+ e. "Original Author" means, in the case of a literary or artistic work,
+    the individual, individuals, entity or entities who created the Work
+    or if no individual or entity can be identified, the publisher; and in
+    addition (i) in the case of a performance the actors, singers,
+    musicians, dancers, and other persons who act, sing, deliver, declaim,
+    play in, interpret or otherwise perform literary or artistic works or
+    expressions of folklore; (ii) in the case of a phonogram the producer
+    being the person or legal entity who first fixes the sounds of a
+    performance or other sounds; and, (iii) in the case of broadcasts, the
+    organization that transmits the broadcast.
+ f. "Work" means the literary and/or artistic work offered under the terms
+    of this License including without limitation any production in the
+    literary, scientific and artistic domain, whatever may be the mode or
+    form of its expression including digital form, such as a book,
+    pamphlet and other writing; a lecture, address, sermon or other work
+    of the same nature; a dramatic or dramatico-musical work; a
+    choreographic work or entertainment in dumb show; a musical
+    composition with or without words; a cinematographic work to which are
+    assimilated works expressed by a process analogous to cinematography;
+    a work of drawing, painting, architecture, sculpture, engraving or
+    lithography; a photographic work to which are assimilated works
+    expressed by a process analogous to photography; a work of applied
+    art; an illustration, map, plan, sketch or three-dimensional work
+    relative to geography, topography, architecture or science; a
+    performance; a broadcast; a phonogram; a compilation of data to the
+    extent it is protected as a copyrightable work; or a work performed by
+    a variety or circus performer to the extent it is not otherwise
+    considered a literary or artistic work.
+ g. "You" means an individual or entity exercising rights under this
+    License who has not previously violated the terms of this License with
+    respect to the Work, or who has received express permission from the
+    Licensor to exercise rights under this License despite a previous
+    violation.
+ h. "Publicly Perform" means to perform public recitations of the Work and
+    to communicate to the public those public recitations, by any means or
+    process, including by wire or wireless means or public digital
+    performances; to make available to the public Works in such a way that
+    members of the public may access these Works from a place and at a
+    place individually chosen by them; to perform the Work to the public
+    by any means or process and the communication to the public of the
+    performances of the Work, including by public digital performance; to
+    broadcast and rebroadcast the Work by any means including signs,
+    sounds or images.
+ i. "Reproduce" means to make copies of the Work by any means including
+    without limitation by sound or visual recordings and the right of
+    fixation and reproducing fixations of the Work, including storage of a
+    protected performance or phonogram in digital form or other electronic
+    medium.
+
+2. Fair Dealing Rights. Nothing in this License is intended to reduce,
+limit, or restrict any uses free from copyright or rights arising from
+limitations or exceptions that are provided for in connection with the
+copyright protection under copyright law or other applicable laws.
+
+3. License Grant. Subject to the terms and conditions of this License,
+Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+perpetual (for the duration of the applicable copyright) license to
+exercise the rights in the Work as stated below:
+
+ a. to Reproduce the Work, to incorporate the Work into one or more
+    Collections, and to Reproduce the Work as incorporated in the
+    Collections;
+ b. to create and Reproduce Adaptations provided that any such Adaptation,
+    including any translation in any medium, takes reasonable steps to
+    clearly label, demarcate or otherwise identify that changes were made
+    to the original Work. For example, a translation could be marked "The
+    original work was translated from English to Spanish," or a
+    modification could indicate "The original work has been modified.";
+ c. to Distribute and Publicly Perform the Work including as incorporated
+    in Collections; and,
+ d. to Distribute and Publicly Perform Adaptations.
+ e. For the avoidance of doubt:
+
+     i. Non-waivable Compulsory License Schemes. In those jurisdictions in
+        which the right to collect royalties through any statutory or
+        compulsory licensing scheme cannot be waived, the Licensor
+        reserves the exclusive right to collect such royalties for any
+        exercise by You of the rights granted under this License;
+    ii. Waivable Compulsory License Schemes. In those jurisdictions in
+        which the right to collect royalties through any statutory or
+        compulsory licensing scheme can be waived, the Licensor waives the
+        exclusive right to collect such royalties for any exercise by You
+        of the rights granted under this License; and,
+   iii. Voluntary License Schemes. The Licensor waives the right to
+        collect royalties, whether individually or, in the event that the
+        Licensor is a member of a collecting society that administers
+        voluntary licensing schemes, via that society, from any exercise
+        by You of the rights granted under this License.
+
+The above rights may be exercised in all media and formats whether now
+known or hereafter devised. The above rights include the right to make
+such modifications as are technically necessary to exercise the rights in
+other media and formats. Subject to Section 8(f), all rights not expressly
+granted by Licensor are hereby reserved.
+
+4. Restrictions. The license granted in Section 3 above is expressly made
+subject to and limited by the following restrictions:
+
+ a. You may Distribute or Publicly Perform the Work only under the terms
+    of this License. You must include a copy of, or the Uniform Resource
+    Identifier (URI) for, this License with every copy of the Work You
+    Distribute or Publicly Perform. You may not offer or impose any terms
+    on the Work that restrict the terms of this License or the ability of
+    the recipient of the Work to exercise the rights granted to that
+    recipient under the terms of the License. You may not sublicense the
+    Work. You must keep intact all notices that refer to this License and
+    to the disclaimer of warranties with every copy of the Work You
+    Distribute or Publicly Perform. When You Distribute or Publicly
+    Perform the Work, You may not impose any effective technological
+    measures on the Work that restrict the ability of a recipient of the
+    Work from You to exercise the rights granted to that recipient under
+    the terms of the License. This Section 4(a) applies to the Work as
+    incorporated in a Collection, but this does not require the Collection
+    apart from the Work itself to be made subject to the terms of this
+    License. If You create a Collection, upon notice from any Licensor You
+    must, to the extent practicable, remove from the Collection any credit
+    as required by Section 4(b), as requested. If You create an
+    Adaptation, upon notice from any Licensor You must, to the extent
+    practicable, remove from the Adaptation any credit as required by
+    Section 4(b), as requested.
+ b. If You Distribute, or Publicly Perform the Work or any Adaptations or
+    Collections, You must, unless a request has been made pursuant to
+    Section 4(a), keep intact all copyright notices for the Work and
+    provide, reasonable to the medium or means You are utilizing: (i) the
+    name of the Original Author (or pseudonym, if applicable) if supplied,
+    and/or if the Original Author and/or Licensor designate another party
+    or parties (e.g., a sponsor institute, publishing entity, journal) for
+    attribution ("Attribution Parties") in Licensor's copyright notice,
+    terms of service or by other reasonable means, the name of such party
+    or parties; (ii) the title of the Work if supplied; (iii) to the
+    extent reasonably practicable, the URI, if any, that Licensor
+    specifies to be associated with the Work, unless such URI does not
+    refer to the copyright notice or licensing information for the Work;
+    and (iv) , consistent with Section 3(b), in the case of an Adaptation,
+    a credit identifying the use of the Work in the Adaptation (e.g.,
+    "French translation of the Work by Original Author," or "Screenplay
+    based on original Work by Original Author"). The credit required by
+    this Section 4 (b) may be implemented in any reasonable manner;
+    provided, however, that in the case of a Adaptation or Collection, at
+    a minimum such credit will appear, if a credit for all contributing
+    authors of the Adaptation or Collection appears, then as part of these
+    credits and in a manner at least as prominent as the credits for the
+    other contributing authors. For the avoidance of doubt, You may only
+    use the credit required by this Section for the purpose of attribution
+    in the manner set out above and, by exercising Your rights under this
+    License, You may not implicitly or explicitly assert or imply any
+    connection with, sponsorship or endorsement by the Original Author,
+    Licensor and/or Attribution Parties, as appropriate, of You or Your
+    use of the Work, without the separate, express prior written
+    permission of the Original Author, Licensor and/or Attribution
+    Parties.
+ c. Except as otherwise agreed in writing by the Licensor or as may be
+    otherwise permitted by applicable law, if You Reproduce, Distribute or
+    Publicly Perform the Work either by itself or as part of any
+    Adaptations or Collections, You must not distort, mutilate, modify or
+    take other derogatory action in relation to the Work which would be
+    prejudicial to the Original Author's honor or reputation. Licensor
+    agrees that in those jurisdictions (e.g. Japan), in which any exercise
+    of the right granted in Section 3(b) of this License (the right to
+    make Adaptations) would be deemed to be a distortion, mutilation,
+    modification or other derogatory action prejudicial to the Original
+    Author's honor and reputation, the Licensor will waive or not assert,
+    as appropriate, this Section, to the fullest extent permitted by the
+    applicable national law, to enable You to reasonably exercise Your
+    right under Section 3(b) of this License (right to make Adaptations)
+    but not otherwise.
+
+5. Representations, Warranties and Disclaimer
+
+UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
+OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
+KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
+INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
+FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
+LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
+WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
+OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+
+6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
+LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
+ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
+ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. Termination
+
+ a. This License and the rights granted hereunder will terminate
+    automatically upon any breach by You of the terms of this License.
+    Individuals or entities who have received Adaptations or Collections
+    from You under this License, however, will not have their licenses
+    terminated provided such individuals or entities remain in full
+    compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
+    survive any termination of this License.
+ b. Subject to the above terms and conditions, the license granted here is
+    perpetual (for the duration of the applicable copyright in the Work).
+    Notwithstanding the above, Licensor reserves the right to release the
+    Work under different license terms or to stop distributing the Work at
+    any time; provided, however that any such election will not serve to
+    withdraw this License (or any other license that has been, or is
+    required to be, granted under the terms of this License), and this
+    License will continue in full force and effect unless terminated as
+    stated above.
+
+8. Miscellaneous
+
+ a. Each time You Distribute or Publicly Perform the Work or a Collection,
+    the Licensor offers to the recipient a license to the Work on the same
+    terms and conditions as the license granted to You under this License.
+ b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
+    offers to the recipient a license to the original Work on the same
+    terms and conditions as the license granted to You under this License.
+ c. If any provision of this License is invalid or unenforceable under
+    applicable law, it shall not affect the validity or enforceability of
+    the remainder of the terms of this License, and without further action
+    by the parties to this agreement, such provision shall be reformed to
+    the minimum extent necessary to make such provision valid and
+    enforceable.
+ d. No term or provision of this License shall be deemed waived and no
+    breach consented to unless such waiver or consent shall be in writing
+    and signed by the party to be charged with such waiver or consent.
+ e. This License constitutes the entire agreement between the parties with
+    respect to the Work licensed here. There are no understandings,
+    agreements or representations with respect to the Work not specified
+    here. Licensor shall not be bound by any additional provisions that
+    may appear in any communication from You. This License may not be
+    modified without the mutual written agreement of the Licensor and You.
+ f. The rights granted under, and the subject matter referenced, in this
+    License were drafted utilizing the terminology of the Berne Convention
+    for the Protection of Literary and Artistic Works (as amended on
+    September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
+    Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
+    and the Universal Copyright Convention (as revised on July 24, 1971).
+    These rights and subject matter take effect in the relevant
+    jurisdiction in which the License terms are sought to be enforced
+    according to the corresponding provisions of the implementation of
+    those treaty provisions in the applicable national law. If the
+    standard suite of rights granted under applicable copyright law
+    includes additional rights not granted under this License, such
+    additional rights are deemed to be included in the License; this
+    License is not intended to restrict the license of any rights under
+    applicable law.
+
+
+Creative Commons Notice
+
+    Creative Commons is not a party to this License, and makes no warranty
+    whatsoever in connection with the Work. Creative Commons will not be
+    liable to You or any party on any legal theory for any damages
+    whatsoever, including without limitation any general, special,
+    incidental or consequential damages arising in connection to this
+    license. Notwithstanding the foregoing two (2) sentences, if Creative
+    Commons has expressly identified itself as the Licensor hereunder, it
+    shall have all rights and obligations of Licensor.
+
+    Except for the limited purpose of indicating to the public that the
+    Work is licensed under the CCPL, Creative Commons does not authorize
+    the use by either party of the trademark "Creative Commons" or any
+    related trademark or logo of Creative Commons without the prior
+    written consent of Creative Commons. Any permitted use will be in
+    compliance with Creative Commons' then-current trademark usage
+    guidelines, as may be published on its website or otherwise made
+    available upon request from time to time. For the avoidance of doubt,
+    this trademark restriction does not form part of this License.
+
+    Creative Commons may be contacted at https://creativecommons.org/.
+
+===============================================================================
+
+The Go Programming Language
+https://golang.org/LICENSE
+
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+===============================================================================
+
+The Rust Programming Language
+https://github.com/rust-lang/rust/blob/master/LICENSE-MIT
+
+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.
+
+===============================================================================
+
+The Rust Programming Language
+https://github.com/rust-lang/rust/blob/master/LICENSE-APACHE
+
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crossbeam-channel/README.md
@@ -0,0 +1,88 @@
+# Crossbeam Channel
+
+[![Build Status](https://travis-ci.org/crossbeam-rs/crossbeam.svg?branch=master)](
+https://travis-ci.org/crossbeam-rs/crossbeam)
+[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](
+https://github.com/crossbeam-rs/crossbeam-channel)
+[![Cargo](https://img.shields.io/crates/v/crossbeam-channel.svg)](
+https://crates.io/crates/crossbeam-channel)
+[![Documentation](https://docs.rs/crossbeam-channel/badge.svg)](
+https://docs.rs/crossbeam-channel)
+[![Rust 1.26+](https://img.shields.io/badge/rust-1.26+-lightgray.svg)](
+https://www.rust-lang.org)
+
+This crate provides multi-producer multi-consumer channels for message passing.
+It is an alternative to [`std::sync::mpsc`] with more features and better performance.
+
+Some highlights:
+
+* [`Sender`]s and [`Receiver`]s can be cloned and shared among threads.
+* Two main kinds of channels are [`bounded`] and [`unbounded`].
+* Convenient extra channels like [`after`], [`never`], and [`tick`].
+* The [`select!`] macro can block on multiple channel operations.
+* [`Select`] can select over a dynamically built list of channel operations.
+* Channels use locks very sparingly for maximum [performance](benchmarks).
+
+[`std::sync::mpsc`]: https://doc.rust-lang.org/std/sync/mpsc/index.html
+[`Sender`]: https://docs.rs/crossbeam-channel/*/crossbeam_channel/struct.Sender.html
+[`Receiver`]: https://docs.rs/crossbeam-channel/*/crossbeam_channel/struct.Receiver.html
+[`bounded`]: https://docs.rs/crossbeam-channel/*/crossbeam_channel/fn.bounded.html
+[`unbounded`]: https://docs.rs/crossbeam-channel/*/crossbeam_channel/fn.unbounded.html
+[`after`]: https://docs.rs/crossbeam-channel/*/crossbeam_channel/fn.after.html
+[`never`]: https://docs.rs/crossbeam-channel/*/crossbeam_channel/fn.never.html
+[`tick`]: https://docs.rs/crossbeam-channel/*/crossbeam_channel/fn.tick.html
+[`select!`]: https://docs.rs/crossbeam-channel/*/crossbeam_channel/macro.select.html
+[`Select`]: https://docs.rs/crossbeam-channel/*/crossbeam_channel/struct.Select.html
+
+## Usage
+
+Add this to your `Cargo.toml`:
+
+```toml
+[dependencies]
+crossbeam-channel = "0.3"
+```
+
+Next, add this to your crate:
+
+```rust
+#[macro_use]
+extern crate crossbeam_channel;
+```
+
+## License
+
+Licensed under either of
+
+ * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
+#### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
+dual licensed as above, without any additional terms or conditions.
+
+#### Third party software
+
+This product includes copies and modifications of software developed by third parties:
+
+* [examples/matching.rs](examples/matching.rs) includes
+  [matching.go](http://www.nada.kth.se/~snilsson/concurrency/src/matching.go) by Stefan Nilsson,
+  licensed under Creative Commons Attribution 3.0 Unported License.
+
+* [src/flavors/array.rs](src/flavors/array.rs) is based on
+  [Bounded MPMC queue](http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue)
+  by Dmitry Vyukov, licensed under the Simplified BSD License and the Apache License, Version 2.0.
+
+* [tests/mpsc.rs](tests/mpsc.rs) includes modifications of code from The Rust Programming Language,
+  licensed under the MIT License and the Apache License, Version 2.0.
+
+* [tests/golang.rs](tests/golang.rs) is based on code from The Go Programming Language, licensed
+  under the 3-Clause BSD License.
+
+See the source code files for more details.
+
+Copies of third party licenses can be found in [LICENSE-THIRD-PARTY](LICENSE-THIRD-PARTY).
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crossbeam-channel/examples/fibonacci.rs
@@ -0,0 +1,27 @@
+//! An asynchronous fibonacci sequence generator.
+
+extern crate crossbeam_channel;
+
+use std::thread;
+
+use crossbeam_channel::{bounded, Sender};
+
+// Sends the Fibonacci sequence into the channel until it becomes disconnected.
+fn fibonacci(sender: Sender<u64>) {
+    let (mut x, mut y) = (0, 1);
+    while sender.send(x).is_ok() {
+        let tmp = x;
+        x = y;
+        y = tmp + y;
+    }
+}
+
+fn main() {
+    let (s, r) = bounded(0);
+    thread::spawn(|| fibonacci(s));
+
+    // Print the first 20 Fibonacci numbers.
+    for num in r.iter().take(20) {
+        println!("{}", num);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crossbeam-channel/examples/matching.rs
@@ -0,0 +1,75 @@
+//! Using `select!` to send and receive on the same channel at the same time.
+//!
+//! This example is based on the following program in Go.
+//!
+//! Source:
+//!   - https://web.archive.org/web/20171209034309/https://www.nada.kth.se/~snilsson/concurrency
+//!   - http://www.nada.kth.se/~snilsson/concurrency/src/matching.go
+//!
+//! Copyright & License:
+//!   - Stefan Nilsson
+//!   - Creative Commons Attribution 3.0 Unported License
+//!   - https://creativecommons.org/licenses/by/3.0/
+//!
+//! ```go
+//! func main() {
+//!     people := []string{"Anna", "Bob", "Cody", "Dave", "Eva"}
+//!     match := make(chan string, 1) // Make room for one unmatched send.
+//!     wg := new(sync.WaitGroup)
+//!     for _, name := range people {
+//!         wg.Add(1)
+//!         go Seek(name, match, wg)
+//!     }
+//!     wg.Wait()
+//!     select {
+//!     case name := <-match:
+//!         fmt.Printf("No one received %s’s message.\n", name)
+//!     default:
+//!         // There was no pending send operation.
+//!     }
+//! }
+//!
+//! // Seek either sends or receives, whichever possible, a name on the match
+//! // channel and notifies the wait group when done.
+//! func Seek(name string, match chan string, wg *sync.WaitGroup) {
+//!     select {
+//!     case peer := <-match:
+//!         fmt.Printf("%s received a message from %s.\n", name, peer)
+//!     case match <- name:
+//!         // Wait for someone to receive my message.
+//!     }
+//!     wg.Done()
+//! }
+//! ```
+
+#[macro_use]
+extern crate crossbeam_channel;
+extern crate crossbeam_utils;
+
+use crossbeam_channel::bounded;
+use crossbeam_utils::thread;
+
+fn main() {
+    let people = vec!["Anna", "Bob", "Cody", "Dave", "Eva"];
+    let (s, r) = bounded(1); // Make room for one unmatched send.
+
+    // Either send my name into the channel or receive someone else's, whatever happens first.
+    let seek = |name, s, r| {
+        select! {
+            recv(r) -> peer => println!("{} received a message from {}.", name, peer.unwrap()),
+            send(s, name) -> _ => {}, // Wait for someone to receive my message.
+        }
+    };
+
+    thread::scope(|scope| {
+        for name in people {
+            let (s, r) = (s.clone(), r.clone());
+            scope.spawn(move |_| seek(name, s, r));
+        }
+    }).unwrap();
+
+    // Check if there is a pending send operation.
+    if let Ok(name) = r.try_recv() {
+        println!("No one received {}’s message.", name);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crossbeam-channel/examples/stopwatch.rs
@@ -0,0 +1,58 @@
+//! Prints the elapsed time every 1 second and quits on Ctrl+C.
+
+#[macro_use]
+extern crate crossbeam_channel;
+extern crate signal_hook;
+
+use std::io;
+use std::thread;
+use std::time::{Duration, Instant};
+
+use crossbeam_channel::{bounded, tick, Receiver};
+use signal_hook::iterator::Signals;
+use signal_hook::SIGINT;
+
+// Creates a channel that gets a message every time `SIGINT` is signalled.
+fn sigint_notifier() -> io::Result<Receiver<()>> {
+    let (s, r) = bounded(100);
+    let signals = Signals::new(&[SIGINT])?;
+
+    thread::spawn(move || {
+        for _ in signals.forever() {
+            if s.send(()).is_err() {
+                break;
+            }
+        }
+    });
+
+    Ok(r)
+}
+
+// Prints the elapsed time.
+fn show(dur: Duration) {
+    println!(
+        "Elapsed: {}.{:03} sec",
+        dur.as_secs(),
+        dur.subsec_nanos() / 1_000_000
+    );
+}
+
+fn main() {
+    let start = Instant::now();
+    let update = tick(Duration::from_secs(1));
+    let ctrl_c = sigint_notifier().unwrap();
+
+    loop {
+        select! {
+            recv(update) -> _ => {
+                show(start.elapsed());
+            }
+            recv(ctrl_c) -> _ => {
+                println!();
+                println!("Goodbye!");
+                show(start.elapsed());
+                break;
+            }
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crossbeam-channel/src/channel.rs
@@ -0,0 +1,1340 @@
+//! The channel interface.
+
+use std::fmt;
+use std::iter::FusedIterator;
+use std::mem;
+use std::panic::{RefUnwindSafe, UnwindSafe};
+use std::sync::Arc;
+use std::time::{Duration, Instant};
+
+use context::Context;
+use counter;
+use err::{RecvError, RecvTimeoutError, SendError, SendTimeoutError, TryRecvError, TrySendError};
+use flavors;
+use select::{Operation, SelectHandle, Token};
+
+/// Creates a channel of unbounded capacity.
+///
+/// This channel has a growable buffer that can hold any number of messages at a time.
+///
+/// # Examples
+///
+/// ```
+/// use std::thread;
+/// use crossbeam_channel::unbounded;
+///
+/// let (s, r) = unbounded();
+///
+/// // Computes the n-th Fibonacci number.
+/// fn fib(n: i32) -> i32 {
+///     if n <= 1 {
+///         n
+///     } else {
+///         fib(n - 1) + fib(n - 2)
+///     }
+/// }
+///
+/// // Spawn an asynchronous computation.
+/// thread::spawn(move || s.send(fib(20)).unwrap());
+///
+/// // Print the result of the computation.
+/// println!("{}", r.recv().unwrap());
+/// ```
+pub fn unbounded<T>() -> (Sender<T>, Receiver<T>) {
+    let (s, r) = counter::new(flavors::list::Channel::new());
+    let s = Sender {
+        flavor: SenderFlavor::List(s),
+    };
+    let r = Receiver {
+        flavor: ReceiverFlavor::List(r),
+    };
+    (s, r)
+}
+
+/// Creates a channel of bounded capacity.
+///
+/// This channel has a buffer that can hold at most `cap` messages at a time.
+///
+/// A special case is zero-capacity channel, which cannot hold any messages. Instead, send and
+/// receive operations must appear at the same time in order to pair up and pass the message over.
+///
+/// # Panics
+///
+/// Panics if the capacity is greater than `usize::max_value() / 4`.
+///
+/// # Examples
+///
+/// A channel of capacity 1:
+///
+/// ```
+/// use std::thread;
+/// use std::time::Duration;
+/// use crossbeam_channel::bounded;
+///
+/// let (s, r) = bounded(1);
+///
+/// // This call returns immediately because there is enough space in the channel.
+/// s.send(1).unwrap();
+///
+/// thread::spawn(move || {
+///     // This call blocks the current thread because the channel is full.
+///     // It will be able to complete only after the first message is received.
+///     s.send(2).unwrap();
+/// });
+///
+/// thread::sleep(Duration::from_secs(1));
+/// assert_eq!(r.recv(), Ok(1));
+/// assert_eq!(r.recv(), Ok(2));
+/// ```
+///
+/// A zero-capacity channel:
+///
+/// ```
+/// use std::thread;
+/// use std::time::Duration;
+/// use crossbeam_channel::bounded;
+///
+/// let (s, r) = bounded(0);
+///
+/// thread::spawn(move || {
+///     // This call blocks the current thread until a receive operation appears
+///     // on the other side of the channel.
+///     s.send(1).unwrap();
+/// });
+///
+/// thread::sleep(Duration::from_secs(1));
+/// assert_eq!(r.recv(), Ok(1));
+/// ```
+pub fn bounded<T>(cap: usize) -> (Sender<T>, Receiver<T>) {
+    if cap == 0 {
+        let (s, r) = counter::new(flavors::zero::Channel::new());
+        let s = Sender {
+            flavor: SenderFlavor::Zero(s),
+        };
+        let r = Receiver {
+            flavor: ReceiverFlavor::Zero(r),
+        };
+        (s, r)
+    } else {
+        let (s, r) = counter::new(flavors::array::Channel::with_capacity(cap));
+        let s = Sender {
+            flavor: SenderFlavor::Array(s),
+        };
+        let r = Receiver {
+            flavor: ReceiverFlavor::Array(r),
+        };
+        (s, r)
+    }
+}
+
+/// Creates a receiver that delivers a message after a certain duration of time.
+///
+/// The channel is bounded with capacity of 1 and never gets disconnected. Exactly one message will
+/// be sent into the channel after `duration` elapses. The message is the instant at which it is
+/// sent.
+///
+/// # Examples
+///
+/// Using an `after` channel for timeouts:
+///
+/// ```
+/// # #[macro_use]
+/// # extern crate crossbeam_channel;
+/// # fn main() {
+/// use std::time::Duration;
+/// use crossbeam_channel::{after, unbounded};
+///
+/// let (s, r) = unbounded::<i32>();
+/// let timeout = Duration::from_millis(100);
+///
+/// select! {
+///     recv(r) -> msg => println!("received {:?}", msg),
+///     recv(after(timeout)) -> _ => println!("timed out"),
+/// }
+/// # }
+/// ```
+///
+/// When the message gets sent:
+///
+/// ```
+/// use std::thread;
+/// use std::time::{Duration, Instant};
+/// use crossbeam_channel::after;
+///
+/// // Converts a number of milliseconds into a `Duration`.
+/// let ms = |ms| Duration::from_millis(ms);
+///
+/// // Returns `true` if `a` and `b` are very close `Instant`s.
+/// let eq = |a, b| a + ms(50) > b && b + ms(50) > a;
+///
+/// let start = Instant::now();
+/// let r = after(ms(100));
+///
+/// thread::sleep(ms(500));
+///
+/// // This message was sent 100 ms from the start and received 500 ms from the start.
+/// assert!(eq(r.recv().unwrap(), start + ms(100)));
+/// assert!(eq(Instant::now(), start + ms(500)));
+/// ```
+pub fn after(duration: Duration) -> Receiver<Instant> {
+    Receiver {
+        flavor: ReceiverFlavor::After(Arc::new(flavors::after::Channel::new(duration))),
+    }
+}
+
+/// Creates a receiver that never delivers messages.
+///
+/// The channel is bounded with capacity of 0 and never gets disconnected.
+///
+/// # Examples
+///
+/// Using a `never` channel to optionally add a timeout to [`select!`]:
+///
+/// ```
+/// # #[macro_use]
+/// # extern crate crossbeam_channel;
+/// # fn main() {
+/// use std::thread;
+/// use std::time::{Duration, Instant};
+/// use crossbeam_channel::{after, never, unbounded};
+///
+/// let (s, r) = unbounded();
+///
+/// thread::spawn(move || {
+///     thread::sleep(Duration::from_secs(1));
+///     s.send(1).unwrap();
+/// });
+///
+/// // Suppose this duration can be a `Some` or a `None`.
+/// let duration = Some(Duration::from_millis(100));
+///
+/// // Create a channel that times out after the specified duration.
+/// let timeout = duration
+///     .map(|d| after(d))
+///     .unwrap_or(never());
+///
+/// select! {
+///     recv(r) -> msg => assert_eq!(msg, Ok(1)),
+///     recv(timeout) -> _ => println!("timed out"),
+/// }
+/// # }
+/// ```
+///
+/// [`select!`]: macro.select.html
+pub fn never<T>() -> Receiver<T> {
+    Receiver {
+        flavor: ReceiverFlavor::Never(flavors::never::Channel::new()),
+    }
+}
+
+/// Creates a receiver that delivers messages periodically.
+///
+/// The channel is bounded with capacity of 1 and never gets disconnected. Messages will be
+/// sent into the channel in intervals of `duration`. Each message is the instant at which it is
+/// sent.
+///
+/// # Examples
+///
+/// Using a `tick` channel to periodically print elapsed time:
+///
+/// ```
+/// use std::time::{Duration, Instant};
+/// use crossbeam_channel::tick;
+///
+/// let start = Instant::now();
+/// let ticker = tick(Duration::from_millis(100));
+///
+/// for _ in 0..5 {
+///     ticker.recv().unwrap();
+///     println!("elapsed: {:?}", start.elapsed());
+/// }
+/// ```
+///
+/// When messages get sent:
+///
+/// ```
+/// use std::thread;
+/// use std::time::{Duration, Instant};
+/// use crossbeam_channel::tick;
+///
+/// // Converts a number of milliseconds into a `Duration`.
+/// let ms = |ms| Duration::from_millis(ms);
+///
+/// // Returns `true` if `a` and `b` are very close `Instant`s.
+/// let eq = |a, b| a + ms(50) > b && b + ms(50) > a;
+///
+/// let start = Instant::now();
+/// let r = tick(ms(100));
+///
+/// // This message was sent 100 ms from the start and received 100 ms from the start.
+/// assert!(eq(r.recv().unwrap(), start + ms(100)));
+/// assert!(eq(Instant::now(), start + ms(100)));
+///
+/// thread::sleep(ms(500));
+///
+/// // This message was sent 200 ms from the start and received 600 ms from the start.
+/// assert!(eq(r.recv().unwrap(), start + ms(200)));
+/// assert!(eq(Instant::now(), start + ms(600)));
+///
+/// // This message was sent 700 ms from the start and received 700 ms from the start.
+/// assert!(eq(r.recv().unwrap(), start + ms(700)));
+/// assert!(eq(Instant::now(), start + ms(700)));
+/// ```
+pub fn tick(duration: Duration) -> Receiver<Instant> {
+    Receiver {
+        flavor: ReceiverFlavor::Tick(Arc::new(flavors::tick::Channel::new(duration))),
+    }
+}
+
+/// The sending side of a channel.
+///
+/// # Examples
+///
+/// ```
+/// use std::thread;
+/// use crossbeam_channel::unbounded;
+///
+/// let (s1, r) = unbounded();
+/// let s2 = s1.clone();
+///
+/// thread::spawn(move || s1.send(1).unwrap());
+/// thread::spawn(move || s2.send(2).unwrap());
+///
+/// let msg1 = r.recv().unwrap();
+/// let msg2 = r.recv().unwrap();
+///
+/// assert_eq!(msg1 + msg2, 3);
+/// ```
+pub struct Sender<T> {
+    flavor: SenderFlavor<T>,
+}
+
+/// Sender flavors.
+enum SenderFlavor<T> {
+    /// Bounded channel based on a preallocated array.
+    Array(counter::Sender<flavors::array::Channel<T>>),
+
+    /// Unbounded channel implemented as a linked list.
+    List(counter::Sender<flavors::list::Channel<T>>),
+
+    /// Zero-capacity channel.
+    Zero(counter::Sender<flavors::zero::Channel<T>>),
+}
+
+unsafe impl<T: Send> Send for Sender<T> {}
+unsafe impl<T: Send> Sync for Sender<T> {}
+
+impl<T> UnwindSafe for Sender<T> {}
+impl<T> RefUnwindSafe for Sender<T> {}
+
+impl<T> Sender<T> {
+    /// Attempts to send a message into the channel without blocking.
+    ///
+    /// This method will either send a message into the channel immediately or return an error if
+    /// the channel is full or disconnected. The returned error contains the original message.
+    ///
+    /// If called on a zero-capacity channel, this method will send the message only if there
+    /// happens to be a receive operation on the other side of the channel at the same time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_channel::{bounded, TrySendError};
+    ///
+    /// let (s, r) = bounded(1);
+    ///
+    /// assert_eq!(s.try_send(1), Ok(()));
+    /// assert_eq!(s.try_send(2), Err(TrySendError::Full(2)));
+    ///
+    /// drop(r);
+    /// assert_eq!(s.try_send(3), Err(TrySendError::Disconnected(3)));
+    /// ```
+    pub fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
+        match &self.flavor {
+            SenderFlavor::Array(chan) => chan.try_send(msg),
+            SenderFlavor::List(chan) => chan.try_send(msg),
+            SenderFlavor::Zero(chan) => chan.try_send(msg),
+        }
+    }
+
+    /// Blocks the current thread until a message is sent or the channel is disconnected.
+    ///
+    /// If the channel is full and not disconnected, this call will block until the send operation
+    /// can proceed. If the channel becomes disconnected, this call will wake up and return an
+    /// error. The returned error contains the original message.
+    ///
+    /// If called on a zero-capacity channel, this method will wait for a receive operation to
+    /// appear on the other side of the channel.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    /// use std::time::Duration;
+    /// use crossbeam_channel::{bounded, SendError};
+    ///
+    /// let (s, r) = bounded(1);
+    /// assert_eq!(s.send(1), Ok(()));
+    ///
+    /// thread::spawn(move || {
+    ///     assert_eq!(r.recv(), Ok(1));
+    ///     thread::sleep(Duration::from_secs(1));
+    ///     drop(r);
+    /// });
+    ///
+    /// assert_eq!(s.send(2), Ok(()));
+    /// assert_eq!(s.send(3), Err(SendError(3)));
+    /// ```
+    pub fn send(&self, msg: T) -> Result<(), SendError<T>> {
+        match &self.flavor {
+            SenderFlavor::Array(chan) => chan.send(msg, None),
+            SenderFlavor::List(chan) => chan.send(msg, None),
+            SenderFlavor::Zero(chan) => chan.send(msg, None),
+        }.map_err(|err| match err {
+            SendTimeoutError::Disconnected(msg) => SendError(msg),
+            SendTimeoutError::Timeout(_) => unreachable!(),
+        })
+    }
+
+    /// Waits for a message to be sent into the channel, but only for a limited time.
+    ///
+    /// If the channel is full and not disconnected, this call will block until the send operation
+    /// can proceed or the operation times out. If the channel becomes disconnected, this call will
+    /// wake up and return an error. The returned error contains the original message.
+    ///
+    /// If called on a zero-capacity channel, this method will wait for a receive operation to
+    /// appear on the other side of the channel.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    /// use std::time::Duration;
+    /// use crossbeam_channel::{bounded, SendTimeoutError};
+    ///
+    /// let (s, r) = bounded(0);
+    ///
+    /// thread::spawn(move || {
+    ///     thread::sleep(Duration::from_secs(1));
+    ///     assert_eq!(r.recv(), Ok(2));
+    ///     drop(r);
+    /// });
+    ///
+    /// assert_eq!(
+    ///     s.send_timeout(1, Duration::from_millis(500)),
+    ///     Err(SendTimeoutError::Timeout(1)),
+    /// );
+    /// assert_eq!(
+    ///     s.send_timeout(2, Duration::from_secs(1)),
+    ///     Ok(()),
+    /// );
+    /// assert_eq!(
+    ///     s.send_timeout(3, Duration::from_millis(500)),
+    ///     Err(SendTimeoutError::Disconnected(3)),
+    /// );
+    /// ```
+    pub fn send_timeout(&self, msg: T, timeout: Duration) -> Result<(), SendTimeoutError<T>> {
+        let deadline = Instant::now() + timeout;
+
+        match &self.flavor {
+            SenderFlavor::Array(chan) => chan.send(msg, Some(deadline)),
+            SenderFlavor::List(chan) => chan.send(msg, Some(deadline)),
+            SenderFlavor::Zero(chan) => chan.send(msg, Some(deadline)),
+        }
+    }
+
+    /// Returns `true` if the channel is empty.
+    ///
+    /// Note: Zero-capacity channels are always empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_channel::unbounded;
+    ///
+    /// let (s, r) = unbounded();
+    /// assert!(s.is_empty());
+    ///
+    /// s.send(0).unwrap();
+    /// assert!(!s.is_empty());
+    /// ```
+    pub fn is_empty(&self) -> bool {
+        match &self.flavor {
+            SenderFlavor::Array(chan) => chan.is_empty(),
+            SenderFlavor::List(chan) => chan.is_empty(),
+            SenderFlavor::Zero(chan) => chan.is_empty(),
+        }
+    }
+
+    /// Returns `true` if the channel is full.
+    ///
+    /// Note: Zero-capacity channels are always full.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_channel::bounded;
+    ///
+    /// let (s, r) = bounded(1);
+    ///
+    /// assert!(!s.is_full());
+    /// s.send(0).unwrap();
+    /// assert!(s.is_full());
+    /// ```
+    pub fn is_full(&self) -> bool {
+        match &self.flavor {
+            SenderFlavor::Array(chan) => chan.is_full(),
+            SenderFlavor::List(chan) => chan.is_full(),
+            SenderFlavor::Zero(chan) => chan.is_full(),
+        }
+    }
+
+    /// Returns the number of messages in the channel.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_channel::unbounded;
+    ///
+    /// let (s, r) = unbounded();
+    /// assert_eq!(s.len(), 0);
+    ///
+    /// s.send(1).unwrap();
+    /// s.send(2).unwrap();
+    /// assert_eq!(s.len(), 2);
+    /// ```
+    pub fn len(&self) -> usize {
+        match &self.flavor {
+            SenderFlavor::Array(chan) => chan.len(),
+            SenderFlavor::List(chan) => chan.len(),
+            SenderFlavor::Zero(chan) => chan.len(),
+        }
+    }
+
+    /// If the channel is bounded, returns its capacity.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_channel::{bounded, unbounded};
+    ///
+    /// let (s, _) = unbounded::<i32>();
+    /// assert_eq!(s.capacity(), None);
+    ///
+    /// let (s, _) = bounded::<i32>(5);
+    /// assert_eq!(s.capacity(), Some(5));
+    ///
+    /// let (s, _) = bounded::<i32>(0);
+    /// assert_eq!(s.capacity(), Some(0));
+    /// ```
+    pub fn capacity(&self) -> Option<usize> {
+        match &self.flavor {
+            SenderFlavor::Array(chan) => chan.capacity(),
+            SenderFlavor::List(chan) => chan.capacity(),
+            SenderFlavor::Zero(chan) => chan.capacity(),
+        }
+    }
+}
+
+impl<T> Drop for Sender<T> {
+    fn drop(&mut self) {
+        unsafe {
+            match &self.flavor {
+                SenderFlavor::Array(chan) => chan.release(|c| c.disconnect()),
+                SenderFlavor::List(chan) => chan.release(|c| c.disconnect()),
+                SenderFlavor::Zero(chan) => chan.release(|c| c.disconnect()),
+            }
+        }
+    }
+}
+
+impl<T> Clone for Sender<T> {
+    fn clone(&self) -> Self {
+        let flavor = match &self.flavor {
+            SenderFlavor::Array(chan) => SenderFlavor::Array(chan.acquire()),
+            SenderFlavor::List(chan) => SenderFlavor::List(chan.acquire()),
+            SenderFlavor::Zero(chan) => SenderFlavor::Zero(chan.acquire()),
+        };
+
+        Sender { flavor }
+    }
+}
+
+impl<T> fmt::Debug for Sender<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Sender { .. }")
+    }
+}
+
+/// The receiving side of a channel.
+///
+/// # Examples
+///
+/// ```
+/// use std::thread;
+/// use std::time::Duration;
+/// use crossbeam_channel::unbounded;
+///
+/// let (s, r) = unbounded();
+///
+/// thread::spawn(move || {
+///     s.send(1);
+///     thread::sleep(Duration::from_secs(1));
+///     s.send(2);
+/// });
+///
+/// assert_eq!(r.recv(), Ok(1)); // Received immediately.
+/// assert_eq!(r.recv(), Ok(2)); // Received after 1 second.
+/// ```
+pub struct Receiver<T> {
+    flavor: ReceiverFlavor<T>,
+}
+
+/// Receiver flavors.
+enum ReceiverFlavor<T> {
+    /// Bounded channel based on a preallocated array.
+    Array(counter::Receiver<flavors::array::Channel<T>>),
+
+    /// Unbounded channel implemented as a linked list.
+    List(counter::Receiver<flavors::list::Channel<T>>),
+
+    /// Zero-capacity channel.
+    Zero(counter::Receiver<flavors::zero::Channel<T>>),
+
+    /// The after flavor.
+    After(Arc<flavors::after::Channel>),
+
+    /// The tick flavor.
+    Tick(Arc<flavors::tick::Channel>),
+
+    /// The never flavor.
+    Never(flavors::never::Channel<T>),
+}
+
+unsafe impl<T: Send> Send for Receiver<T> {}
+unsafe impl<T: Send> Sync for Receiver<T> {}
+
+impl<T> UnwindSafe for Receiver<T> {}
+impl<T> RefUnwindSafe for Receiver<T> {}
+
+impl<T> Receiver<T> {
+    /// Attempts to receive a message from the channel without blocking.
+    ///
+    /// This method will either receive a message from the channel immediately or return an error
+    /// if the channel is empty.
+    ///
+    /// If called on a zero-capacity channel, this method will receive a message only if there
+    /// happens to be a send operation on the other side of the channel at the same time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_channel::{unbounded, TryRecvError};
+    ///
+    /// let (s, r) = unbounded();
+    /// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
+    ///
+    /// s.send(5).unwrap();
+    /// drop(s);
+    ///
+    /// assert_eq!(r.try_recv(), Ok(5));
+    /// assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected));
+    /// ```
+    pub fn try_recv(&self) -> Result<T, TryRecvError> {
+        match &self.flavor {
+            ReceiverFlavor::Array(chan) => chan.try_recv(),
+            ReceiverFlavor::List(chan) => chan.try_recv(),
+            ReceiverFlavor::Zero(chan) => chan.try_recv(),
+            ReceiverFlavor::After(chan) => {
+                let msg = chan.try_recv();
+                unsafe {
+                    mem::transmute_copy::<Result<Instant, TryRecvError>, Result<T, TryRecvError>>(
+                        &msg,
+                    )
+                }
+            }
+            ReceiverFlavor::Tick(chan) => {
+                let msg = chan.try_recv();
+                unsafe {
+                    mem::transmute_copy::<Result<Instant, TryRecvError>, Result<T, TryRecvError>>(
+                        &msg,
+                    )
+                }
+            }
+            ReceiverFlavor::Never(chan) => chan.try_recv(),
+        }
+    }
+
+    /// Blocks the current thread until a message is received or the channel is empty and
+    /// disconnected.
+    ///
+    /// If the channel is empty and not disconnected, this call will block until the receive
+    /// operation can proceed. If the channel is empty and becomes disconnected, this call will
+    /// wake up and return an error.
+    ///
+    /// If called on a zero-capacity channel, this method will wait for a send operation to appear
+    /// on the other side of the channel.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    /// use std::time::Duration;
+    /// use crossbeam_channel::{unbounded, RecvError};
+    ///
+    /// let (s, r) = unbounded();
+    ///
+    /// thread::spawn(move || {
+    ///     thread::sleep(Duration::from_secs(1));
+    ///     s.send(5).unwrap();
+    ///     drop(s);
+    /// });
+    ///
+    /// assert_eq!(r.recv(), Ok(5));
+    /// assert_eq!(r.recv(), Err(RecvError));
+    /// ```
+    pub fn recv(&self) -> Result<T, RecvError> {
+        match &self.flavor {
+            ReceiverFlavor::Array(chan) => chan.recv(None),
+            ReceiverFlavor::List(chan) => chan.recv(None),
+            ReceiverFlavor::Zero(chan) => chan.recv(None),
+            ReceiverFlavor::After(chan) => {
+                let msg = chan.recv(None);
+                unsafe {
+                    mem::transmute_copy::<
+                        Result<Instant, RecvTimeoutError>,
+                        Result<T, RecvTimeoutError>,
+                    >(&msg)
+                }
+            }
+            ReceiverFlavor::Tick(chan) => {
+                let msg = chan.recv(None);
+                unsafe {
+                    mem::transmute_copy::<
+                        Result<Instant, RecvTimeoutError>,
+                        Result<T, RecvTimeoutError>,
+                    >(&msg)
+                }
+            }
+            ReceiverFlavor::Never(chan) => chan.recv(None),
+        }.map_err(|_| RecvError)
+    }
+
+    /// Waits for a message to be received from the channel, but only for a limited time.
+    ///
+    /// If the channel is empty and not disconnected, this call will block until the receive
+    /// operation can proceed or the operation times out. If the channel is empty and becomes
+    /// disconnected, this call will wake up and return an error.
+    ///
+    /// If called on a zero-capacity channel, this method will wait for a send operation to appear
+    /// on the other side of the channel.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    /// use std::time::Duration;
+    /// use crossbeam_channel::{unbounded, RecvTimeoutError};
+    ///
+    /// let (s, r) = unbounded();
+    ///
+    /// thread::spawn(move || {
+    ///     thread::sleep(Duration::from_secs(1));
+    ///     s.send(5).unwrap();
+    ///     drop(s);
+    /// });
+    ///
+    /// assert_eq!(
+    ///     r.recv_timeout(Duration::from_millis(500)),
+    ///     Err(RecvTimeoutError::Timeout),
+    /// );
+    /// assert_eq!(
+    ///     r.recv_timeout(Duration::from_secs(1)),
+    ///     Ok(5),
+    /// );
+    /// assert_eq!(
+    ///     r.recv_timeout(Duration::from_secs(1)),
+    ///     Err(RecvTimeoutError::Disconnected),
+    /// );
+    /// ```
+    pub fn recv_timeout(&self, timeout: Duration) -> Result<T, RecvTimeoutError> {
+        let deadline = Instant::now() + timeout;
+
+        match &self.flavor {
+            ReceiverFlavor::Array(chan) => chan.recv(Some(deadline)),
+            ReceiverFlavor::List(chan) => chan.recv(Some(deadline)),
+            ReceiverFlavor::Zero(chan) => chan.recv(Some(deadline)),
+            ReceiverFlavor::After(chan) => {
+                let msg = chan.recv(Some(deadline));
+                unsafe {
+                    mem::transmute_copy::<
+                        Result<Instant, RecvTimeoutError>,
+                        Result<T, RecvTimeoutError>,
+                    >(&msg)
+                }
+            }
+            ReceiverFlavor::Tick(chan) => {
+                let msg = chan.recv(Some(deadline));
+                unsafe {
+                    mem::transmute_copy::<
+                        Result<Instant, RecvTimeoutError>,
+                        Result<T, RecvTimeoutError>,
+                    >(&msg)
+                }
+            }
+            ReceiverFlavor::Never(chan) => chan.recv(Some(deadline)),
+        }
+    }
+
+    /// Returns `true` if the channel is empty.
+    ///
+    /// Note: Zero-capacity channels are always empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_channel::unbounded;
+    ///
+    /// let (s, r) = unbounded();
+    ///
+    /// assert!(r.is_empty());
+    /// s.send(0).unwrap();
+    /// assert!(!r.is_empty());
+    /// ```
+    pub fn is_empty(&self) -> bool {
+        match &self.flavor {
+            ReceiverFlavor::Array(chan) => chan.is_empty(),
+            ReceiverFlavor::List(chan) => chan.is_empty(),
+            ReceiverFlavor::Zero(chan) => chan.is_empty(),
+            ReceiverFlavor::After(chan) => chan.is_empty(),
+            ReceiverFlavor::Tick(chan) => chan.is_empty(),
+            ReceiverFlavor::Never(chan) => chan.is_empty(),
+        }
+    }
+
+    /// Returns `true` if the channel is full.
+    ///
+    /// Note: Zero-capacity channels are always full.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_channel::bounded;
+    ///
+    /// let (s, r) = bounded(1);
+    ///
+    /// assert!(!r.is_full());
+    /// s.send(0).unwrap();
+    /// assert!(r.is_full());
+    /// ```
+    pub fn is_full(&self) -> bool {
+        match &self.flavor {
+            ReceiverFlavor::Array(chan) => chan.is_full(),
+            ReceiverFlavor::List(chan) => chan.is_full(),
+            ReceiverFlavor::Zero(chan) => chan.is_full(),
+            ReceiverFlavor::After(chan) => chan.is_full(),
+            ReceiverFlavor::Tick(chan) => chan.is_full(),
+            ReceiverFlavor::Never(chan) => chan.is_full(),
+        }
+    }
+
+    /// Returns the number of messages in the channel.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_channel::unbounded;
+    ///
+    /// let (s, r) = unbounded();
+    /// assert_eq!(r.len(), 0);
+    ///
+    /// s.send(1).unwrap();
+    /// s.send(2).unwrap();
+    /// assert_eq!(r.len(), 2);
+    /// ```
+    pub fn len(&self) -> usize {
+        match &self.flavor {
+            ReceiverFlavor::Array(chan) => chan.len(),
+            ReceiverFlavor::List(chan) => chan.len(),
+            ReceiverFlavor::Zero(chan) => chan.len(),
+            ReceiverFlavor::After(chan) => chan.len(),
+            ReceiverFlavor::Tick(chan) => chan.len(),
+            ReceiverFlavor::Never(chan) => chan.len(),
+        }
+    }
+
+    /// If the channel is bounded, returns its capacity.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_channel::{bounded, unbounded};
+    ///
+    /// let (_, r) = unbounded::<i32>();
+    /// assert_eq!(r.capacity(), None);
+    ///
+    /// let (_, r) = bounded::<i32>(5);
+    /// assert_eq!(r.capacity(), Some(5));
+    ///
+    /// let (_, r) = bounded::<i32>(0);
+    /// assert_eq!(r.capacity(), Some(0));
+    /// ```
+    pub fn capacity(&self) -> Option<usize> {
+        match &self.flavor {
+            ReceiverFlavor::Array(chan) => chan.capacity(),
+            ReceiverFlavor::List(chan) => chan.capacity(),
+            ReceiverFlavor::Zero(chan) => chan.capacity(),
+            ReceiverFlavor::After(chan) => chan.capacity(),
+            ReceiverFlavor::Tick(chan) => chan.capacity(),
+            ReceiverFlavor::Never(chan) => chan.capacity(),
+        }
+    }
+
+    /// A blocking iterator over messages in the channel.
+    ///
+    /// Each call to [`next`] blocks waiting for the next message and then returns it. However, if
+    /// the channel becomes empty and disconnected, it returns [`None`] without blocking.
+    ///
+    /// [`next`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next
+    /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    /// use crossbeam_channel::unbounded;
+    ///
+    /// let (s, r) = unbounded();
+    ///
+    /// thread::spawn(move || {
+    ///     s.send(1).unwrap();
+    ///     s.send(2).unwrap();
+    ///     s.send(3).unwrap();
+    ///     drop(s); // Disconnect the channel.
+    /// });
+    ///
+    /// // Collect all messages from the channel.
+    /// // Note that the call to `collect` blocks until the sender is dropped.
+    /// let v: Vec<_> = r.iter().collect();
+    ///
+    /// assert_eq!(v, [1, 2, 3]);
+    /// ```
+    pub fn iter(&self) -> Iter<T> {
+        Iter { receiver: self }
+    }
+
+    /// A non-blocking iterator over messages in the channel.
+    ///
+    /// Each call to [`next`] returns a message if there is one ready to be received. The iterator
+    /// never blocks waiting for the next message.
+    ///
+    /// [`next`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    /// use std::time::Duration;
+    /// use crossbeam_channel::unbounded;
+    ///
+    /// let (s, r) = unbounded::<i32>();
+    ///
+    /// thread::spawn(move || {
+    ///     s.send(1).unwrap();
+    ///     thread::sleep(Duration::from_secs(1));
+    ///     s.send(2).unwrap();
+    ///     thread::sleep(Duration::from_secs(2));
+    ///     s.send(3).unwrap();
+    /// });
+    ///
+    /// thread::sleep(Duration::from_secs(2));
+    ///
+    /// // Collect all messages from the channel without blocking.
+    /// // The third message hasn't been sent yet so we'll collect only the first two.
+    /// let v: Vec<_> = r.try_iter().collect();
+    ///
+    /// assert_eq!(v, [1, 2]);
+    /// ```
+    pub fn try_iter(&self) -> TryIter<T> {
+        TryIter { receiver: self }
+    }
+}
+
+impl<T> Drop for Receiver<T> {
+    fn drop(&mut self) {
+        unsafe {
+            match &self.flavor {
+                ReceiverFlavor::Array(chan) => chan.release(|c| c.disconnect()),
+                ReceiverFlavor::List(chan) => chan.release(|c| c.disconnect()),
+                ReceiverFlavor::Zero(chan) => chan.release(|c| c.disconnect()),
+                ReceiverFlavor::After(_) => {},
+                ReceiverFlavor::Tick(_) => {},
+                ReceiverFlavor::Never(_) => {},
+            }
+        }
+    }
+}
+
+impl<T> Clone for Receiver<T> {
+    fn clone(&self) -> Self {
+        let flavor = match &self.flavor {
+            ReceiverFlavor::Array(chan) => ReceiverFlavor::Array(chan.acquire()),
+            ReceiverFlavor::List(chan) => ReceiverFlavor::List(chan.acquire()),
+            ReceiverFlavor::Zero(chan) => ReceiverFlavor::Zero(chan.acquire()),
+            ReceiverFlavor::After(chan) => ReceiverFlavor::After(chan.clone()),
+            ReceiverFlavor::Tick(chan) => ReceiverFlavor::Tick(chan.clone()),
+            ReceiverFlavor::Never(_) => ReceiverFlavor::Never(flavors::never::Channel::new()),
+        };
+
+        Receiver { flavor }
+    }
+}
+
+impl<T> fmt::Debug for Receiver<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Receiver { .. }")
+    }
+}
+
+impl<'a, T> IntoIterator for &'a Receiver<T> {
+    type Item = T;
+    type IntoIter = Iter<'a, T>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter()
+    }
+}
+
+impl<T> IntoIterator for Receiver<T> {
+    type Item = T;
+    type IntoIter = IntoIter<T>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        IntoIter { receiver: self }
+    }
+}
+
+/// A blocking iterator over messages in a channel.
+///
+/// Each call to [`next`] blocks waiting for the next message and then returns it. However, if the
+/// channel becomes empty and disconnected, it returns [`None`] without blocking.
+///
+/// [`next`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next
+/// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None
+///
+/// # Examples
+///
+/// ```
+/// use std::thread;
+/// use crossbeam_channel::unbounded;
+///
+/// let (s, r) = unbounded();
+///
+/// thread::spawn(move || {
+///     s.send(1).unwrap();
+///     s.send(2).unwrap();
+///     s.send(3).unwrap();
+///     drop(s); // Disconnect the channel.
+/// });
+///
+/// // Collect all messages from the channel.
+/// // Note that the call to `collect` blocks until the sender is dropped.
+/// let v: Vec<_> = r.iter().collect();
+///
+/// assert_eq!(v, [1, 2, 3]);
+/// ```
+pub struct Iter<'a, T: 'a> {
+    receiver: &'a Receiver<T>,
+}
+
+impl<'a, T> FusedIterator for Iter<'a, T> {}
+
+impl<'a, T> Iterator for Iter<'a, T> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.receiver.recv().ok()
+    }
+}
+
+impl<'a, T> fmt::Debug for Iter<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Iter { .. }")
+    }
+}
+
+/// A non-blocking iterator over messages in a channel.
+///
+/// Each call to [`next`] returns a message if there is one ready to be received. The iterator
+/// never blocks waiting for the next message.
+///
+/// [`next`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next
+///
+/// # Examples
+///
+/// ```
+/// use std::thread;
+/// use std::time::Duration;
+/// use crossbeam_channel::unbounded;
+///
+/// let (s, r) = unbounded::<i32>();
+///
+/// thread::spawn(move || {
+///     s.send(1).unwrap();
+///     thread::sleep(Duration::from_secs(1));
+///     s.send(2).unwrap();
+///     thread::sleep(Duration::from_secs(2));
+///     s.send(3).unwrap();
+/// });
+///
+/// thread::sleep(Duration::from_secs(2));
+///
+/// // Collect all messages from the channel without blocking.
+/// // The third message hasn't been sent yet so we'll collect only the first two.
+/// let v: Vec<_> = r.try_iter().collect();
+///
+/// assert_eq!(v, [1, 2]);
+/// ```
+pub struct TryIter<'a, T: 'a> {
+    receiver: &'a Receiver<T>,
+}
+
+impl<'a, T> Iterator for TryIter<'a, T> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.receiver.try_recv().ok()
+    }
+}
+
+impl<'a, T> fmt::Debug for TryIter<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("TryIter { .. }")
+    }
+}
+
+/// A blocking iterator over messages in a channel.
+///
+/// Each call to [`next`] blocks waiting for the next message and then returns it. However, if the
+/// channel becomes empty and disconnected, it returns [`None`] without blocking.
+///
+/// [`next`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next
+/// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None
+///
+/// # Examples
+///
+/// ```
+/// use std::thread;
+/// use crossbeam_channel::unbounded;
+///
+/// let (s, r) = unbounded();
+///
+/// thread::spawn(move || {
+///     s.send(1).unwrap();
+///     s.send(2).unwrap();
+///     s.send(3).unwrap();
+///     drop(s); // Disconnect the channel.
+/// });
+///
+/// // Collect all messages from the channel.
+/// // Note that the call to `collect` blocks until the sender is dropped.
+/// let v: Vec<_> = r.into_iter().collect();
+///
+/// assert_eq!(v, [1, 2, 3]);
+/// ```
+pub struct IntoIter<T> {
+    receiver: Receiver<T>,
+}
+
+impl<T> FusedIterator for IntoIter<T> {}
+
+impl<T> Iterator for IntoIter<T> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.receiver.recv().ok()
+    }
+}
+
+impl<T> fmt::Debug for IntoIter<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("IntoIter { .. }")
+    }
+}
+
+impl<T> SelectHandle for Sender<T> {
+    fn try_select(&self, token: &mut Token) -> bool {
+        match &self.flavor {
+            SenderFlavor::Array(chan) => chan.sender().try_select(token),
+            SenderFlavor::List(chan) => chan.sender().try_select(token),
+            SenderFlavor::Zero(chan) => chan.sender().try_select(token),
+        }
+    }
+
+    fn deadline(&self) -> Option<Instant> {
+        None
+    }
+
+    fn register(&self, oper: Operation, cx: &Context) -> bool {
+        match &self.flavor {
+            SenderFlavor::Array(chan) => chan.sender().register(oper, cx),
+            SenderFlavor::List(chan) => chan.sender().register(oper, cx),
+            SenderFlavor::Zero(chan) => chan.sender().register(oper, cx),
+        }
+    }
+
+    fn unregister(&self, oper: Operation) {
+        match &self.flavor {
+            SenderFlavor::Array(chan) => chan.sender().unregister(oper),
+            SenderFlavor::List(chan) => chan.sender().unregister(oper),
+            SenderFlavor::Zero(chan) => chan.sender().unregister(oper),
+        }
+    }
+
+    fn accept(&self, token: &mut Token, cx: &Context) -> bool {
+        match &self.flavor {
+            SenderFlavor::Array(chan) => chan.sender().accept(token, cx),
+            SenderFlavor::List(chan) => chan.sender().accept(token, cx),
+            SenderFlavor::Zero(chan) => chan.sender().accept(token, cx),
+        }
+    }
+
+    fn is_ready(&self) -> bool {
+        match &self.flavor {
+            SenderFlavor::Array(chan) => chan.sender().is_ready(),
+            SenderFlavor::List(chan) => chan.sender().is_ready(),
+            SenderFlavor::Zero(chan) => chan.sender().is_ready(),
+        }
+    }
+
+    fn watch(&self, oper: Operation, cx: &Context) -> bool {
+        match &self.flavor {
+            SenderFlavor::Array(chan) => chan.sender().watch(oper, cx),
+            SenderFlavor::List(chan) => chan.sender().watch(oper, cx),
+            SenderFlavor::Zero(chan) => chan.sender().watch(oper, cx),
+        }
+    }
+
+    fn unwatch(&self, oper: Operation) {
+        match &self.flavor {
+            SenderFlavor::Array(chan) => chan.sender().unwatch(oper),
+            SenderFlavor::List(chan) => chan.sender().unwatch(oper),
+            SenderFlavor::Zero(chan) => chan.sender().unwatch(oper),
+        }
+    }
+}
+
+impl<T> SelectHandle for Receiver<T> {
+    fn try_select(&self, token: &mut Token) -> bool {
+        match &self.flavor {
+            ReceiverFlavor::Array(chan) => chan.receiver().try_select(token),
+            ReceiverFlavor::List(chan) => chan.receiver().try_select(token),
+            ReceiverFlavor::Zero(chan) => chan.receiver().try_select(token),
+            ReceiverFlavor::After(chan) => chan.try_select(token),
+            ReceiverFlavor::Tick(chan) => chan.try_select(token),
+            ReceiverFlavor::Never(chan) => chan.try_select(token),
+        }
+    }
+
+    fn deadline(&self) -> Option<Instant> {
+        match &self.flavor {
+            ReceiverFlavor::Array(_) => None,
+            ReceiverFlavor::List(_) => None,
+            ReceiverFlavor::Zero(_) => None,
+            ReceiverFlavor::After(chan) => chan.deadline(),
+            ReceiverFlavor::Tick(chan) => chan.deadline(),
+            ReceiverFlavor::Never(chan) => chan.deadline(),
+        }
+    }
+
+    fn register(&self, oper: Operation, cx: &Context) -> bool {
+        match &self.flavor {
+            ReceiverFlavor::Array(chan) => chan.receiver().register(oper, cx),
+            ReceiverFlavor::List(chan) => chan.receiver().register(oper, cx),
+            ReceiverFlavor::Zero(chan) => chan.receiver().register(oper, cx),
+            ReceiverFlavor::After(chan) => chan.register(oper, cx),
+            ReceiverFlavor::Tick(chan) => chan.register(oper, cx),
+            ReceiverFlavor::Never(chan) => chan.register(oper, cx),
+        }
+    }
+
+    fn unregister(&self, oper: Operation) {
+        match &self.flavor {
+            ReceiverFlavor::Array(chan) => chan.receiver().unregister(oper),
+            ReceiverFlavor::List(chan) => chan.receiver().unregister(oper),
+            ReceiverFlavor::Zero(chan) => chan.receiver().unregister(oper),
+            ReceiverFlavor::After(chan) => chan.unregister(oper),
+            ReceiverFlavor::Tick(chan) => chan.unregister(oper),
+            ReceiverFlavor::Never(chan) => chan.unregister(oper),
+        }
+    }
+
+    fn accept(&self, token: &mut Token, cx: &Context) -> bool {
+        match &self.flavor {
+            ReceiverFlavor::Array(chan) => chan.receiver().accept(token, cx),
+            ReceiverFlavor::List(chan) => chan.receiver().accept(token, cx),
+            ReceiverFlavor::Zero(chan) => chan.receiver().accept(token, cx),
+            ReceiverFlavor::After(chan) => chan.accept(token, cx),
+            ReceiverFlavor::Tick(chan) => chan.accept(token, cx),
+            ReceiverFlavor::Never(chan) => chan.accept(token, cx),
+        }
+    }
+
+    fn is_ready(&self) -> bool {
+        match &self.flavor {
+            ReceiverFlavor::Array(chan) => chan.receiver().is_ready(),
+            ReceiverFlavor::List(chan) => chan.receiver().is_ready(),
+            ReceiverFlavor::Zero(chan) => chan.receiver().is_ready(),
+            ReceiverFlavor::After(chan) => chan.is_ready(),
+            ReceiverFlavor::Tick(chan) => chan.is_ready(),
+            ReceiverFlavor::Never(chan) => chan.is_ready(),
+        }
+    }
+
+    fn watch(&self, oper: Operation, cx: &Context) -> bool {
+        match &self.flavor {
+            ReceiverFlavor::Array(chan) => chan.receiver().watch(oper, cx),
+            ReceiverFlavor::List(chan) => chan.receiver().watch(oper, cx),
+            ReceiverFlavor::Zero(chan) => chan.receiver().watch(oper, cx),
+            ReceiverFlavor::After(chan) => chan.watch(oper, cx),
+            ReceiverFlavor::Tick(chan) => chan.watch(oper, cx),
+            ReceiverFlavor::Never(chan) => chan.watch(oper, cx),
+        }
+    }
+
+    fn unwatch(&self, oper: Operation) {
+        match &self.flavor {
+            ReceiverFlavor::Array(chan) => chan.receiver().unwatch(oper),
+            ReceiverFlavor::List(chan) => chan.receiver().unwatch(oper),
+            ReceiverFlavor::Zero(chan) => chan.receiver().unwatch(oper),
+            ReceiverFlavor::After(chan) => chan.unwatch(oper),
+            ReceiverFlavor::Tick(chan) => chan.unwatch(oper),
+            ReceiverFlavor::Never(chan) => chan.unwatch(oper),
+        }
+    }
+}
+
+/// Writes a message into the channel.
+pub unsafe fn write<T>(s: &Sender<T>, token: &mut Token, msg: T) -> Result<(), T> {
+    match &s.flavor {
+        SenderFlavor::Array(chan) => chan.write(token, msg),
+        SenderFlavor::List(chan) => chan.write(token, msg),
+        SenderFlavor::Zero(chan) => chan.write(token, msg),
+    }
+}
+
+/// Reads a message from the channel.
+pub unsafe fn read<T>(r: &Receiver<T>, token: &mut Token) -> Result<T, ()> {
+    match &r.flavor {
+        ReceiverFlavor::Array(chan) => chan.read(token),
+        ReceiverFlavor::List(chan) => chan.read(token),
+        ReceiverFlavor::Zero(chan) => chan.read(token),
+        ReceiverFlavor::After(chan) => {
+            mem::transmute_copy::<Result<Instant, ()>, Result<T, ()>>(&chan.read(token))
+        }
+        ReceiverFlavor::Tick(chan) => {
+            mem::transmute_copy::<Result<Instant, ()>, Result<T, ()>>(&chan.read(token))
+        }
+        ReceiverFlavor::Never(chan) => chan.read(token),
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crossbeam-channel/src/context.rs
@@ -0,0 +1,189 @@
+//! Thread-local context used in select.
+
+use std::cell::Cell;
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::Arc;
+use std::thread::{self, Thread, ThreadId};
+use std::time::Instant;
+
+use crossbeam_utils::Backoff;
+
+use select::Selected;
+
+/// Thread-local context used in select.
+#[derive(Clone)]
+pub struct Context {
+    inner: Arc<Inner>,
+}
+
+/// Inner representation of `Context`.
+struct Inner {
+    /// Selected operation.
+    select: AtomicUsize,
+
+    /// A slot into which another thread may store a pointer to its `Packet`.
+    packet: AtomicUsize,
+
+    /// Thread handle.
+    thread: Thread,
+
+    /// Thread id.
+    thread_id: ThreadId,
+}
+
+impl Context {
+    /// Creates a new context for the duration of the closure.
+    #[inline]
+    pub fn with<F, R>(f: F) -> R
+    where
+        F: FnOnce(&Context) -> R,
+    {
+        thread_local! {
+            /// Cached thread-local context.
+            static CONTEXT: Cell<Option<Context>> = Cell::new(Some(Context::new()));
+        }
+
+        let mut f = Some(f);
+        let mut f = move |cx: &Context| -> R {
+            let f = f.take().unwrap();
+            f(cx)
+        };
+
+        CONTEXT
+            .try_with(|cell| match cell.take() {
+                None => f(&Context::new()),
+                Some(cx) => {
+                    cx.reset();
+                    let res = f(&cx);
+                    cell.set(Some(cx));
+                    res
+                }
+            }).unwrap_or_else(|_| f(&Context::new()))
+    }
+
+    /// Creates a new `Context`.
+    #[cold]
+    fn new() -> Context {
+        Context {
+            inner: Arc::new(Inner {
+                select: AtomicUsize::new(Selected::Waiting.into()),
+                packet: AtomicUsize::new(0),
+                thread: thread::current(),
+                thread_id: thread::current().id(),
+            }),
+        }
+    }
+
+    /// Resets `select` and `packet`.
+    #[inline]
+    fn reset(&self) {
+        self.inner
+            .select
+            .store(Selected::Waiting.into(), Ordering::Release);
+        self.inner.packet.store(0, Ordering::Release);
+    }
+
+    /// Attempts to select an operation.
+    ///
+    /// On failure, the previously selected operation is returned.
+    #[inline]
+    pub fn try_select(&self, select: Selected) -> Result<(), Selected> {
+        self.inner
+            .select
+            .compare_exchange(
+                Selected::Waiting.into(),
+                select.into(),
+                Ordering::AcqRel,
+                Ordering::Acquire,
+            )
+            .map(|_| ())
+            .map_err(|e| e.into())
+    }
+
+    /// Returns the selected operation.
+    #[inline]
+    pub fn selected(&self) -> Selected {
+        Selected::from(self.inner.select.load(Ordering::Acquire))
+    }
+
+    /// Stores a packet.
+    ///
+    /// This method must be called after `try_select` succeeds and there is a packet to provide.
+    #[inline]
+    pub fn store_packet(&self, packet: usize) {
+        if packet != 0 {
+            self.inner.packet.store(packet, Ordering::Release);
+        }
+    }
+
+    /// Waits until a packet is provided and returns it.
+    #[inline]
+    pub fn wait_packet(&self) -> usize {
+        let backoff = Backoff::new();
+        loop {
+            let packet = self.inner.packet.load(Ordering::Acquire);
+            if packet != 0 {
+                return packet;
+            }
+            backoff.snooze();
+        }
+    }
+
+    /// Waits until an operation is selected and returns it.
+    ///
+    /// If the deadline is reached, `Selected::Aborted` will be selected.
+    #[inline]
+    pub fn wait_until(&self, deadline: Option<Instant>) -> Selected {
+        // Spin for a short time, waiting until an operation is selected.
+        let backoff = Backoff::new();
+        loop {
+            let sel = Selected::from(self.inner.select.load(Ordering::Acquire));
+            if sel != Selected::Waiting {
+                return sel;
+            }
+
+            if backoff.is_complete() {
+                break;
+            } else {
+                backoff.snooze();
+            }
+        }
+
+        loop {
+            // Check whether an operation has been selected.
+            let sel = Selected::from(self.inner.select.load(Ordering::Acquire));
+            if sel != Selected::Waiting {
+                return sel;
+            }
+
+            // If there's a deadline, park the current thread until the deadline is reached.
+            if let Some(end) = deadline {
+                let now = Instant::now();
+
+                if now < end {
+                    thread::park_timeout(end - now);
+                } else {
+                    // The deadline has been reached. Try aborting select.
+                    return match self.try_select(Selected::Aborted) {
+                        Ok(()) => Selected::Aborted,
+                        Err(s) => s,
+                    };
+                }
+            } else {
+                thread::park();
+            }
+        }
+    }
+
+    /// Unparks the thread this context belongs to.
+    #[inline]
+    pub fn unpark(&self) {
+        self.inner.thread.unpark();
+    }
+
+    /// Returns the id of the thread this context belongs to.
+    #[inline]
+    pub fn thread_id(&self) -> ThreadId {
+        self.inner.thread_id
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crossbeam-channel/src/counter.rs
@@ -0,0 +1,132 @@
+///! Reference counter for channels.
+
+use std::isize;
+use std::ops;
+use std::process;
+use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
+
+/// Reference counter internals.
+struct Counter<C> {
+    /// The number of senders associated with the channel.
+    senders: AtomicUsize,
+
+    /// The number of receivers associated with the channel.
+    receivers: AtomicUsize,
+
+    /// If `true`, either the sending or receiving side has been dropped.
+    disconnected: AtomicBool,
+
+    /// The internal channel.
+    chan: C,
+}
+
+/// Wraps a channel into the reference counter.
+pub fn new<C>(chan: C) -> (Sender<C>, Receiver<C>) {
+    let counter = Box::into_raw(Box::new(Counter {
+        senders: AtomicUsize::new(1),
+        receivers: AtomicUsize::new(1),
+        disconnected: AtomicBool::new(false),
+        chan,
+    }));
+    let s = Sender { counter };
+    let r = Receiver { counter };
+    (s, r)
+}
+
+/// The sending side.
+pub struct Sender<C> {
+    counter: *mut Counter<C>,
+}
+
+impl<C> Sender<C> {
+    /// Returns the internal `Counter`.
+    fn counter(&self) -> &Counter<C> {
+        unsafe { &*self.counter }
+    }
+
+    /// Acquires another sender reference.
+    pub fn acquire(&self) -> Sender<C> {
+        let count = self.counter().senders.fetch_add(1, Ordering::Relaxed);
+
+        // Cloning senders and calling `mem::forget` on the clones could potentially overflow the
+        // counter. It's very difficult to recover sensibly from such degenerate scenarios so we
+        // just abort when the count becomes very large.
+        if count > isize::MAX as usize {
+            process::abort();
+        }
+
+        Sender {
+            counter: self.counter,
+        }
+    }
+
+    /// Releases the sender reference.
+    ///
+    /// Function `f` will be called if this is the last sender reference.
+    pub unsafe fn release<F: FnOnce(&C)>(&self, f: F) {
+        if self.counter().senders.fetch_sub(1, Ordering::AcqRel) == 1 {
+            f(&self.counter().chan);
+
+            if self.counter().disconnected.swap(true, Ordering::AcqRel) {
+                drop(Box::from_raw(self.counter));
+            }
+        }
+    }
+}
+
+impl<C> ops::Deref for Sender<C> {
+    type Target = C;
+
+    fn deref(&self) -> &C {
+        &self.counter().chan
+    }
+}
+
+/// The receiving side.
+pub struct Receiver<C> {
+    counter: *mut Counter<C>,
+}
+
+impl<C> Receiver<C> {
+    /// Returns the internal `Counter`.
+    fn counter(&self) -> &Counter<C> {
+        unsafe { &*self.counter }
+    }
+
+    /// Acquires another receiver reference.
+    pub fn acquire(&self) -> Receiver<C> {
+        let count = self.counter().receivers.fetch_add(1, Ordering::Relaxed);
+
+        // Cloning receivers and calling `mem::forget` on the clones could potentially overflow the
+        // counter. It's very difficult to recover sensibly from such degenerate scenarios so we
+        // just abort when the count becomes very large.
+        if count > isize::MAX as usize {
+            process::abort();
+        }
+
+        Receiver {
+            counter: self.counter,
+        }
+    }
+
+    /// Releases the receiver reference.
+    ///
+    /// Function `f` will be called if this is the last receiver reference.
+    pub unsafe fn release<F: FnOnce(&C)>(&self, f: F) {
+        if self.counter().receivers.fetch_sub(1, Ordering::AcqRel) == 1 {
+            f(&self.counter().chan);
+
+            if self.counter().disconnected.swap(true, Ordering::AcqRel) {
+                drop(Box::from_raw(self.counter));
+            }
+        }
+    }
+}
+
+impl<C> ops::Deref for Receiver<C> {
+    type Target = C;
+
+    fn deref(&self) -> &C {
+        &self.counter().chan
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crossbeam-channel/src/err.rs
@@ -0,0 +1,451 @@
+use std::error;
+use std::fmt;
+
+/// An error returned from the [`send`] method.
+///
+/// The message could not be sent because the channel is disconnected.
+///
+/// The error contains the message so it can be recovered.
+///
+/// [`send`]: struct.Sender.html#method.send
+#[derive(PartialEq, Eq, Clone, Copy)]
+pub struct SendError<T>(pub T);
+
+/// An error returned from the [`try_send`] method.
+///
+/// The error contains the message being sent so it can be recovered.
+///
+/// [`try_send`]: struct.Sender.html#method.try_send
+#[derive(PartialEq, Eq, Clone, Copy)]
+pub enum TrySendError<T> {
+    /// The message could not be sent because the channel is full.
+    ///
+    /// If this is a zero-capacity channel, then the error indicates that there was no receiver
+    /// available to receive the message at the time.
+    Full(T),
+
+    /// The message could not be sent because the channel is disconnected.
+    Disconnected(T),
+}
+
+/// An error returned from the [`send_timeout`] method.
+///
+/// The error contains the message being sent so it can be recovered.
+///
+/// [`send_timeout`]: struct.Sender.html#method.send_timeout
+#[derive(PartialEq, Eq, Clone, Copy)]
+pub enum SendTimeoutError<T> {
+    /// The message could not be sent because the channel is full and the operation timed out.
+    ///
+    /// If this is a zero-capacity channel, then the error indicates that there was no receiver
+    /// available to receive the message and the operation timed out.
+    Timeout(T),
+
+    /// The message could not be sent because the channel is disconnected.
+    Disconnected(T),
+}
+
+/// An error returned from the [`recv`] method.
+///
+/// A message could not be received because the channel is empty and disconnected.
+///
+/// [`recv`]: struct.Receiver.html#method.recv
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct RecvError;
+
+/// An error returned from the [`try_recv`] method.
+///
+/// [`try_recv`]: struct.Receiver.html#method.recv
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub enum TryRecvError {
+    /// A message could not be received because the channel is empty.
+    ///
+    /// If this is a zero-capacity channel, then the error indicates that there was no sender
+    /// available to send a message at the time.
+    Empty,
+
+    /// The message could not be received because the channel is empty and disconnected.
+    Disconnected,
+}
+
+/// An error returned from the [`recv_timeout`] method.
+///
+/// [`recv_timeout`]: struct.Receiver.html#method.recv_timeout
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub enum RecvTimeoutError {
+    /// A message could not be received because the channel is empty and the operation timed out.
+    ///
+    /// If this is a zero-capacity channel, then the error indicates that there was no sender
+    /// available to send a message and the operation timed out.
+    Timeout,
+
+    /// The message could not be received because the channel is empty and disconnected.
+    Disconnected,
+}
+
+/// An error returned from the [`try_select`] method.
+///
+/// Failed because none of the channel operations were ready.
+///
+/// [`try_select`]: struct.Select.html#method.try_select
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct TrySelectError;
+
+/// An error returned from the [`select_timeout`] method.
+///
+/// Failed because none of the channel operations became ready before the timeout.
+///
+/// [`select_timeout`]: struct.Select.html#method.select_timeout
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct SelectTimeoutError;
+
+/// An error returned from the [`try_ready`] method.
+///
+/// Failed because none of the channel operations were ready.
+///
+/// [`try_ready`]: struct.Select.html#method.try_ready
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct TryReadyError;
+
+/// An error returned from the [`ready_timeout`] method.
+///
+/// Failed because none of the channel operations became ready before the timeout.
+///
+/// [`ready_timeout`]: struct.Select.html#method.ready_timeout
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ReadyTimeoutError;
+
+impl<T> fmt::Debug for SendError<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "SendError(..)".fmt(f)
+    }
+}
+
+impl<T> fmt::Display for SendError<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "sending on a disconnected channel".fmt(f)
+    }
+}
+
+impl<T: Send> error::Error for SendError<T> {
+    fn description(&self) -> &str {
+        "sending on a disconnected channel"
+    }
+
+    fn cause(&self) -> Option<&error::Error> {
+        None
+    }
+}
+
+impl<T> SendError<T> {
+    /// Unwraps the message.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_channel::unbounded;
+    ///
+    /// let (s, r) = unbounded();
+    /// drop(r);
+    ///
+    /// if let Err(err) = s.send("foo") {
+    ///     assert_eq!(err.into_inner(), "foo");
+    /// }
+    /// ```
+    pub fn into_inner(self) -> T {
+        self.0
+    }
+}
+
+impl<T> fmt::Debug for TrySendError<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            TrySendError::Full(..) => "Full(..)".fmt(f),
+            TrySendError::Disconnected(..) => "Disconnected(..)".fmt(f),
+        }
+    }
+}
+
+impl<T> fmt::Display for TrySendError<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            TrySendError::Full(..) => "sending on a full channel".fmt(f),
+            TrySendError::Disconnected(..) => "sending on a disconnected channel".fmt(f),
+        }
+    }
+}
+
+impl<T: Send> error::Error for TrySendError<T> {
+    fn description(&self) -> &str {
+        match *self {
+            TrySendError::Full(..) => "sending on a full channel",
+            TrySendError::Disconnected(..) => "sending on a disconnected channel",
+        }
+    }
+
+    fn cause(&self) -> Option<&error::Error> {
+        None
+    }
+}
+
+impl<T> From<SendError<T>> for TrySendError<T> {
+    fn from(err: SendError<T>) -> TrySendError<T> {
+        match err {
+            SendError(t) => TrySendError::Disconnected(t),
+        }
+    }
+}
+
+impl<T> TrySendError<T> {
+    /// Unwraps the message.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_channel::bounded;
+    ///
+    /// let (s, r) = bounded(0);
+    ///
+    /// if let Err(err) = s.try_send("foo") {
+    ///     assert_eq!(err.into_inner(), "foo");
+    /// }
+    /// ```
+    pub fn into_inner(self) -> T {
+        match self {
+            TrySendError::Full(v) => v,
+            TrySendError::Disconnected(v) => v,
+        }
+    }
+
+    /// Returns `true` if the send operation failed because the channel is full.
+    pub fn is_full(&self) -> bool {
+        match self {
+            TrySendError::Full(_) => true,
+            _ => false,
+        }
+    }
+
+    /// Returns `true` if the send operation failed because the channel is disconnected.
+    pub fn is_disconnected(&self) -> bool {
+        match self {
+            TrySendError::Disconnected(_) => true,
+            _ => false,
+        }
+    }
+}
+
+impl<T> fmt::Debug for SendTimeoutError<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "SendTimeoutError(..)".fmt(f)
+    }
+}
+
+impl<T> fmt::Display for SendTimeoutError<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            SendTimeoutError::Timeout(..) => "timed out waiting on send operation".fmt(f),
+            SendTimeoutError::Disconnected(..) => "sending on a disconnected channel".fmt(f),
+        }
+    }
+}
+
+impl<T: Send> error::Error for SendTimeoutError<T> {
+    fn description(&self) -> &str {
+        "sending on an empty and disconnected channel"
+    }
+
+    fn cause(&self) -> Option<&error::Error> {
+        None
+    }
+}
+
+impl<T> From<SendError<T>> for SendTimeoutError<T> {
+    fn from(err: SendError<T>) -> SendTimeoutError<T> {
+        match err {
+            SendError(e) => SendTimeoutError::Disconnected(e),
+        }
+    }
+}
+
+impl<T> SendTimeoutError<T> {
+    /// Unwraps the message.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::time::Duration;
+    /// use crossbeam_channel::unbounded;
+    ///
+    /// let (s, r) = unbounded();
+    ///
+    /// if let Err(err) = s.send_timeout("foo", Duration::from_secs(1)) {
+    ///     assert_eq!(err.into_inner(), "foo");
+    /// }
+    /// ```
+    pub fn into_inner(self) -> T {
+        match self {
+            SendTimeoutError::Timeout(v) => v,
+            SendTimeoutError::Disconnected(v) => v,
+        }
+    }
+
+    /// Returns `true` if the send operation timed out.
+    pub fn is_timeout(&self) -> bool {
+        match self {
+            SendTimeoutError::Timeout(_) => true,
+            _ => false,
+        }
+    }
+
+    /// Returns `true` if the send operation failed because the channel is disconnected.
+    pub fn is_disconnected(&self) -> bool {
+        match self {
+            SendTimeoutError::Disconnected(_) => true,
+            _ => false,
+        }
+    }
+}
+
+impl fmt::Display for RecvError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "receiving on an empty and disconnected channel".fmt(f)
+    }
+}
+
+impl error::Error for RecvError {
+    fn description(&self) -> &str {
+        "receiving on an empty and disconnected channel"
+    }
+
+    fn cause(&self) -> Option<&error::Error> {
+        None
+    }
+}
+
+impl fmt::Display for TryRecvError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            TryRecvError::Empty => "receiving on an empty channel".fmt(f),
+            TryRecvError::Disconnected => "receiving on an empty and disconnected channel".fmt(f),
+        }
+    }
+}
+
+impl error::Error for TryRecvError {
+    fn description(&self) -> &str {
+        match *self {
+            TryRecvError::Empty => "receiving on an empty channel",
+            TryRecvError::Disconnected => "receiving on an empty and disconnected channel",
+        }
+    }
+
+    fn cause(&self) -> Option<&error::Error> {
+        None
+    }
+}
+
+impl From<RecvError> for TryRecvError {
+    fn from(err: RecvError) -> TryRecvError {
+        match err {
+            RecvError => TryRecvError::Disconnected,
+        }
+    }
+}
+
+impl TryRecvError {
+    /// Returns `true` if the receive operation failed because the channel is empty.
+    pub fn is_empty(&self) -> bool {
+        match self {
+            TryRecvError::Empty => true,
+            _ => false,
+        }
+    }
+
+    /// Returns `true` if the receive operation failed because the channel is disconnected.
+    pub fn is_disconnected(&self) -> bool {
+        match self {
+            TryRecvError::Disconnected => true,
+            _ => false,
+        }
+    }
+}
+
+impl fmt::Display for RecvTimeoutError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            RecvTimeoutError::Timeout => "timed out waiting on receive operation".fmt(f),
+            RecvTimeoutError::Disconnected => "channel is empty and disconnected".fmt(f),
+        }
+    }
+}
+
+impl error::Error for RecvTimeoutError {
+    fn description(&self) -> &str {
+        match *self {
+            RecvTimeoutError::Timeout => "timed out waiting on receive operation",
+            RecvTimeoutError::Disconnected => "channel is empty and disconnected",
+        }
+    }
+
+    fn cause(&self) -> Option<&error::Error> {
+        None
+    }
+}
+
+impl From<RecvError> for RecvTimeoutError {
+    fn from(err: RecvError) -> RecvTimeoutError {
+        match err {
+            RecvError => RecvTimeoutError::Disconnected,
+        }
+    }
+}
+
+impl RecvTimeoutError {
+    /// Returns `true` if the receive operation timed out.
+    pub fn is_timeout(&self) -> bool {
+        match self {
+            RecvTimeoutError::Timeout => true,
+            _ => false,
+        }
+    }
+
+    /// Returns `true` if the receive operation failed because the channel is disconnected.
+    pub fn is_disconnected(&self) -> bool {
+        match self {
+            RecvTimeoutError::Disconnected => true,
+            _ => false,
+        }
+    }
+}
+
+impl fmt::Display for TrySelectError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "all operations in select would block".fmt(f)
+    }
+}
+
+impl error::Error for TrySelectError {
+    fn description(&self) -> &str {
+        "all operations in select would block"
+    }
+
+    fn cause(&self) -> Option<&error::Error> {
+        None
+    }
+}
+
+impl fmt::Display for SelectTimeoutError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "timed out waiting on select".fmt(f)
+    }
+}
+
+impl error::Error for SelectTimeoutError {
+    fn description(&self) -> &str {
+        "timed out waiting on select"
+    }
+
+    fn cause(&self) -> Option<&error::Error> {
+        None
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crossbeam-channel/src/flavors/after.rs
@@ -0,0 +1,200 @@
+//! Channel that delivers a message after a certain amount of time.
+//!
+//! Messages cannot be sent into this kind of channel; they are materialized on demand.
+
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::thread;
+use std::time::{Duration, Instant};
+
+use context::Context;
+use err::{RecvTimeoutError, TryRecvError};
+use select::{Operation, SelectHandle, Token};
+use utils;
+
+/// Result of a receive operation.
+pub type AfterToken = Option<Instant>;
+
+/// Channel that delivers a message after a certain amount of time.
+pub struct Channel {
+    /// The instant at which the message will be delivered.
+    delivery_time: Instant,
+
+    /// `true` if the message has been received.
+    received: AtomicBool,
+}
+
+impl Channel {
+    /// Creates a channel that delivers a message after a certain duration of time.
+    #[inline]
+    pub fn new(dur: Duration) -> Self {
+        Channel {
+            delivery_time: Instant::now() + dur,
+            received: AtomicBool::new(false),
+        }
+    }
+
+    /// Attempts to receive a message without blocking.
+    #[inline]
+    pub fn try_recv(&self) -> Result<Instant, TryRecvError> {
+        // We use relaxed ordering because this is just an optional optimistic check.
+        if self.received.load(Ordering::Relaxed) {
+            // The message has already been received.
+            return Err(TryRecvError::Empty);
+        }
+
+        if Instant::now() < self.delivery_time {
+            // The message was not delivered yet.
+            return Err(TryRecvError::Empty);
+        }
+
+        // Try receiving the message if it is still available.
+        if !self.received.swap(true, Ordering::SeqCst) {
+            // Success! Return delivery time as the message.
+            Ok(self.delivery_time)
+        } else {
+            // The message was already received.
+            Err(TryRecvError::Empty)
+        }
+    }
+
+    /// Receives a message from the channel.
+    #[inline]
+    pub fn recv(&self, deadline: Option<Instant>) -> Result<Instant, RecvTimeoutError> {
+        // We use relaxed ordering because this is just an optional optimistic check.
+        if self.received.load(Ordering::Relaxed) {
+            // The message has already been received.
+            utils::sleep_until(deadline);
+            return Err(RecvTimeoutError::Timeout);
+        }
+
+        // Wait until the message is received or the deadline is reached.
+        loop {
+            let now = Instant::now();
+
+            // Check if we can receive the next message.
+            if now >= self.delivery_time {
+                break;
+            }
+
+            // Check if the deadline has been reached.
+            if let Some(d) = deadline {
+                if now >= d {
+                    return Err(RecvTimeoutError::Timeout);
+                }
+
+                thread::sleep(self.delivery_time.min(d) - now);
+            } else {
+                thread::sleep(self.delivery_time - now);
+            }
+        }
+
+        // Try receiving the message if it is still available.
+        if !self.received.swap(true, Ordering::SeqCst) {
+            // Success! Return the message, which is the instant at which it was delivered.
+            Ok(self.delivery_time)
+        } else {
+            // The message was already received. Block forever.
+            utils::sleep_until(None);
+            unreachable!()
+        }
+    }
+
+    /// Reads a message from the channel.
+    #[inline]
+    pub unsafe fn read(&self, token: &mut Token) -> Result<Instant, ()> {
+        token.after.ok_or(())
+    }
+
+    /// Returns `true` if the channel is empty.
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        // We use relaxed ordering because this is just an optional optimistic check.
+        if self.received.load(Ordering::Relaxed) {
+            return true;
+        }
+
+        // If the delivery time hasn't been reached yet, the channel is empty.
+        if Instant::now() < self.delivery_time {
+            return true;
+        }
+
+        // The delivery time has been reached. The channel is empty only if the message has already
+        // been received.
+        self.received.load(Ordering::SeqCst)
+    }
+
+    /// Returns `true` if the channel is full.
+    #[inline]
+    pub fn is_full(&self) -> bool {
+        !self.is_empty()
+    }
+
+    /// Returns the number of messages in the channel.
+    #[inline]
+    pub fn len(&self) -> usize {
+        if self.is_empty() {
+            0
+        } else {
+            1
+        }
+    }
+
+    /// Returns the capacity of the channel.
+    #[inline]
+    pub fn capacity(&self) -> Option<usize> {
+        Some(1)
+    }
+}
+
+impl SelectHandle for Channel {
+    #[inline]
+    fn try_select(&self, token: &mut Token) -> bool {
+        match self.try_recv() {
+            Ok(msg) => {
+                token.after = Some(msg);
+                true
+            }
+            Err(TryRecvError::Disconnected) => {
+                token.after = None;
+                true
+            }
+            Err(TryRecvError::Empty) => false,
+        }
+    }
+
+    #[inline]
+    fn deadline(&self) -> Option<Instant> {
+        // We use relaxed ordering because this is just an optional optimistic check.
+        if self.received.load(Ordering::Relaxed) {
+            None
+        } else {
+            Some(self.delivery_time)
+        }
+    }
+
+    #[inline]
+    fn register(&self, _oper: Operation, _cx: &Context) -> bool {
+        self.is_ready()
+    }
+
+    #[inline]
+    fn unregister(&self, _oper: Operation) {}
+
+    #[inline]
+    fn accept(&self, token: &mut Token, _cx: &Context) -> bool {
+        self.try_select(token)
+    }
+
+    #[inline]
+    fn is_ready(&self) -> bool {
+        !self.is_empty()
+    }
+
+    #[inline]
+    fn watch(&self, _oper: Operation, _cx: &Context) -> bool {
+        self.is_ready()
+    }
+
+    #[inline]
+    fn unwatch(&self, _oper: Operation) {}
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crossbeam-channel/src/flavors/array.rs
@@ -0,0 +1,637 @@
+//! Bounded channel based on a preallocated array.
+//!
+//! This flavor has a fixed, positive capacity.
+//!
+//! The implementation is based on Dmitry Vyukov's bounded MPMC queue.
+//!
+//! Source:
+//!   - http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue
+//!   - https://docs.google.com/document/d/1yIAYmbvL3JxOKOjuCyon7JhW4cSv1wy5hC0ApeGMV9s/pub
+//!
+//! Copyright & License:
+//!   - Copyright (c) 2010-2011 Dmitry Vyukov
+//!   - Simplified BSD License and Apache License, Version 2.0
+//!   - http://www.1024cores.net/home/code-license
+
+use std::cell::UnsafeCell;
+use std::marker::PhantomData;
+use std::mem;
+use std::ptr;
+use std::sync::atomic::{self, AtomicUsize, Ordering};
+use std::time::Instant;
+
+use crossbeam_utils::{Backoff, CachePadded};
+
+use context::Context;
+use err::{RecvTimeoutError, SendTimeoutError, TryRecvError, TrySendError};
+use select::{Operation, SelectHandle, Selected, Token};
+use waker::SyncWaker;
+
+/// A slot in a channel.
+struct Slot<T> {
+    /// The current stamp.
+    stamp: AtomicUsize,
+
+    /// The message in this slot.
+    msg: UnsafeCell<T>,
+}
+
+/// The token type for the array flavor.
+pub struct ArrayToken {
+    /// Slot to read from or write to.
+    slot: *const u8,
+
+    /// Stamp to store into the slot after reading or writing.
+    stamp: usize,
+}
+
+impl Default for ArrayToken {
+    #[inline]
+    fn default() -> Self {
+        ArrayToken {
+            slot: ptr::null(),
+            stamp: 0,
+        }
+    }
+}
+
+/// Bounded channel based on a preallocated array.
+pub struct Channel<T> {
+    /// The head of the channel.
+    ///
+    /// This value is a "stamp" consisting of an index into the buffer, a mark bit, and a lap, but
+    /// packed into a single `usize`. The lower bits represent the index, while the upper bits
+    /// represent the lap. The mark bit in the head is always zero.
+    ///
+    /// Messages are popped from the head of the channel.
+    head: CachePadded<AtomicUsize>,
+
+    /// The tail of the channel.
+    ///
+    /// This value is a "stamp" consisting of an index into the buffer, a mark bit, and a lap, but
+    /// packed into a single `usize`. The lower bits represent the index, while the upper bits
+    /// represent the lap. The mark bit indicates that the channel is disconnected.
+    ///
+    /// Messages are pushed into the tail of the channel.
+    tail: CachePadded<AtomicUsize>,
+
+    /// The buffer holding slots.
+    buffer: *mut Slot<T>,
+
+    /// The channel capacity.
+    cap: usize,
+
+    /// A stamp with the value of `{ lap: 1, mark: 0, index: 0 }`.
+    one_lap: usize,
+
+    /// If this bit is set in the tail, that means the channel is disconnected.
+    mark_bit: usize,
+
+    /// Senders waiting while the channel is full.
+    senders: SyncWaker,
+
+    /// Receivers waiting while the channel is empty and not disconnected.
+    receivers: SyncWaker,
+
+    /// Indicates that dropping a `Channel<T>` may drop values of type `T`.
+    _marker: PhantomData<T>,
+}
+
+impl<T> Channel<T> {
+    /// Creates a bounded channel of capacity `cap`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the capacity is not in the range `1 ..= usize::max_value() / 4`.
+    pub fn with_capacity(cap: usize) -> Self {
+        assert!(cap > 0, "capacity must be positive");
+
+        // Make sure there are at least two most significant bits: one to encode laps and one more
+        // to indicate that the channel is disconnected. If we can't reserve two bits, then panic.
+        // In that case, the buffer is likely too large to allocate anyway.
+        let cap_limit = usize::max_value() / 4;
+        assert!(
+            cap <= cap_limit,
+            "channel capacity is too large: {} > {}",
+            cap,
+            cap_limit
+        );
+
+        // Compute constants `mark_bit` and `one_lap`.
+        let mark_bit = (cap + 1).next_power_of_two();
+        let one_lap = mark_bit * 2;
+
+        // Head is initialized to `{ lap: 0, mark: 0, index: 0 }`.
+        let head = 0;
+        // Tail is initialized to `{ lap: 0, mark: 0, index: 0 }`.
+        let tail = 0;
+
+        // Allocate a buffer of `cap` slots.
+        let buffer = {
+            let mut v = Vec::<Slot<T>>::with_capacity(cap);
+            let ptr = v.as_mut_ptr();
+            mem::forget(v);
+            ptr
+        };
+
+        // Initialize stamps in the slots.
+        for i in 0..cap {
+            unsafe {
+                // Set the stamp to `{ lap: 0, mark: 0, index: i }`.
+                let slot = buffer.add(i);
+                ptr::write(&mut (*slot).stamp, AtomicUsize::new(i));
+            }
+        }
+
+        Channel {
+            buffer,
+            cap,
+            one_lap,
+            mark_bit,
+            head: CachePadded::new(AtomicUsize::new(head)),
+            tail: CachePadded::new(AtomicUsize::new(tail)),
+            senders: SyncWaker::new(),
+            receivers: SyncWaker::new(),
+            _marker: PhantomData,
+        }
+    }
+
+    /// Returns a receiver handle to the channel.
+    pub fn receiver(&self) -> Receiver<T> {
+        Receiver(self)
+    }
+
+    /// Returns a sender handle to the channel.
+    pub fn sender(&self) -> Sender<T> {
+        Sender(self)
+    }
+
+    /// Attempts to reserve a slot for sending a message.
+    fn start_send(&self, token: &mut Token) -> bool {
+        let backoff = Backoff::new();
+        let mut tail = self.tail.load(Ordering::Relaxed);
+
+        loop {
+            // Check if the channel is disconnected.
+            if tail & self.mark_bit != 0 {
+                token.array.slot = ptr::null();
+                token.array.stamp = 0;
+                return true;
+            }
+
+            // Deconstruct the tail.
+            let index = tail & (self.mark_bit - 1);
+            let lap = tail & !(self.one_lap - 1);
+
+            // Inspect the corresponding slot.
+            let slot = unsafe { &*self.buffer.add(index) };
+            let stamp = slot.stamp.load(Ordering::Acquire);
+
+            // If the tail and the stamp match, we may attempt to push.
+            if tail == stamp {
+                let new_tail = if index + 1 < self.cap {
+                    // Same lap, incremented index.
+                    // Set to `{ lap: lap, mark: 0, index: index + 1 }`.
+                    tail + 1
+                } else {
+                    // One lap forward, index wraps around to zero.
+                    // Set to `{ lap: lap.wrapping_add(1), mark: 0, index: 0 }`.
+                    lap.wrapping_add(self.one_lap)
+                };
+
+                // Try moving the tail.
+                match self
+                    .tail
+                    .compare_exchange_weak(tail, new_tail, Ordering::SeqCst, Ordering::Relaxed)
+                {
+                    Ok(_) => {
+                        // Prepare the token for the follow-up call to `write`.
+                        token.array.slot = slot as *const Slot<T> as *const u8;
+                        token.array.stamp = tail + 1;
+                        return true;
+                    }
+                    Err(t) => {
+                        tail = t;
+                        backoff.spin();
+                    }
+                }
+            } else if stamp.wrapping_add(self.one_lap) == tail + 1 {
+                atomic::fence(Ordering::SeqCst);
+                let head = self.head.load(Ordering::Relaxed);
+
+                // If the head lags one lap behind the tail as well...
+                if head.wrapping_add(self.one_lap) == tail {
+                    // ...then the channel is full.
+                    return false;
+                }
+
+                backoff.spin();
+                tail = self.tail.load(Ordering::Relaxed);
+            } else {
+                // Snooze because we need to wait for the stamp to get updated.
+                backoff.snooze();
+                tail = self.tail.load(Ordering::Relaxed);
+            }
+        }
+    }
+
+    /// Writes a message into the channel.
+    pub unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> {
+        // If there is no slot, the channel is disconnected.
+        if token.array.slot.is_null() {
+            return Err(msg);
+        }
+
+        let slot: &Slot<T> = &*(token.array.slot as *const Slot<T>);
+
+        // Write the message into the slot and update the stamp.
+        slot.msg.get().write(msg);
+        slot.stamp.store(token.array.stamp, Ordering::Release);
+
+        // Wake a sleeping receiver.
+        self.receivers.notify();
+        Ok(())
+    }
+
+    /// Attempts to reserve a slot for receiving a message.
+    fn start_recv(&self, token: &mut Token) -> bool {
+        let backoff = Backoff::new();
+        let mut head = self.head.load(Ordering::Relaxed);
+
+        loop {
+            // Deconstruct the head.
+            let index = head & (self.mark_bit - 1);
+            let lap = head & !(self.one_lap - 1);
+
+            // Inspect the corresponding slot.
+            let slot = unsafe { &*self.buffer.add(index) };
+            let stamp = slot.stamp.load(Ordering::Acquire);
+
+            // If the the stamp is ahead of the head by 1, we may attempt to pop.
+            if head + 1 == stamp {
+                let new = if index + 1 < self.cap {
+                    // Same lap, incremented index.
+                    // Set to `{ lap: lap, mark: 0, index: index + 1 }`.
+                    head + 1
+                } else {
+                    // One lap forward, index wraps around to zero.
+                    // Set to `{ lap: lap.wrapping_add(1), mark: 0, index: 0 }`.
+                    lap.wrapping_add(self.one_lap)
+                };
+
+                // Try moving the head.
+                match self
+                    .head
+                    .compare_exchange_weak(head, new, Ordering::SeqCst, Ordering::Relaxed)
+                {
+                    Ok(_) => {
+                        // Prepare the token for the follow-up call to `read`.
+                        token.array.slot = slot as *const Slot<T> as *const u8;
+                        token.array.stamp = head.wrapping_add(self.one_lap);
+                        return true;
+                    }
+                    Err(h) => {
+                        head = h;
+                        backoff.spin();
+                    }
+                }
+            } else if stamp == head {
+                atomic::fence(Ordering::SeqCst);
+                let tail = self.tail.load(Ordering::Relaxed);
+
+                // If the tail equals the head, that means the channel is empty.
+                if (tail & !self.mark_bit) == head {
+                    // If the channel is disconnected...
+                    if tail & self.mark_bit != 0 {
+                        // ...then receive an error.
+                        token.array.slot = ptr::null();
+                        token.array.stamp = 0;
+                        return true;
+                    } else {
+                        // Otherwise, the receive operation is not ready.
+                        return false;
+                    }
+                }
+
+                backoff.spin();
+                head = self.head.load(Ordering::Relaxed);
+            } else {
+                // Snooze because we need to wait for the stamp to get updated.
+                backoff.snooze();
+                head = self.head.load(Ordering::Relaxed);
+            }
+        }
+    }
+
+    /// Reads a message from the channel.
+    pub unsafe fn read(&self, token: &mut Token) -> Result<T, ()> {
+        if token.array.slot.is_null() {
+            // The channel is disconnected.
+            return Err(());
+        }
+
+        let slot: &Slot<T> = &*(token.array.slot as *const Slot<T>);
+
+        // Read the message from the slot and update the stamp.
+        let msg = slot.msg.get().read();
+        slot.stamp.store(token.array.stamp, Ordering::Release);
+
+        // Wake a sleeping sender.
+        self.senders.notify();
+        Ok(msg)
+    }
+
+    /// Attempts to send a message into the channel.
+    pub fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
+        let token = &mut Token::default();
+        if self.start_send(token) {
+            unsafe { self.write(token, msg).map_err(TrySendError::Disconnected) }
+        } else {
+            Err(TrySendError::Full(msg))
+        }
+    }
+
+    /// Sends a message into the channel.
+    pub fn send(&self, msg: T, deadline: Option<Instant>) -> Result<(), SendTimeoutError<T>> {
+        let token = &mut Token::default();
+        loop {
+            // Try sending a message several times.
+            let backoff = Backoff::new();
+            loop {
+                if self.start_send(token) {
+                    let res = unsafe { self.write(token, msg) };
+                    return res.map_err(SendTimeoutError::Disconnected);
+                }
+
+                if backoff.is_complete() {
+                    break;
+                } else {
+                    backoff.snooze();
+                }
+            }
+
+            Context::with(|cx| {
+                // Prepare for blocking until a receiver wakes us up.
+                let oper = Operation::hook(token);
+                self.senders.register(oper, cx);
+
+                // Has the channel become ready just now?
+                if !self.is_full() || self.is_disconnected() {
+                    let _ = cx.try_select(Selected::Aborted);
+                }
+
+                // Block the current thread.
+                let sel = cx.wait_until(deadline);
+
+                match sel {
+                    Selected::Waiting => unreachable!(),
+                    Selected::Aborted | Selected::Disconnected => {
+                        self.senders.unregister(oper).unwrap();
+                    }
+                    Selected::Operation(_) => {}
+                }
+            });
+
+            if let Some(d) = deadline {
+                if Instant::now() >= d {
+                    return Err(SendTimeoutError::Timeout(msg));
+                }
+            }
+        }
+    }
+
+    /// Attempts to receive a message without blocking.
+    pub fn try_recv(&self) -> Result<T, TryRecvError> {
+        let token = &mut Token::default();
+
+        if self.start_recv(token) {
+            unsafe { self.read(token).map_err(|_| TryRecvError::Disconnected) }
+        } else {
+            Err(TryRecvError::Empty)
+        }
+    }
+
+    /// Receives a message from the channel.
+    pub fn recv(&self, deadline: Option<Instant>) -> Result<T, RecvTimeoutError> {
+        let token = &mut Token::default();
+        loop {
+            // Try receiving a message several times.
+            let backoff = Backoff::new();
+            loop {
+                if self.start_recv(token) {
+                    let res = unsafe { self.read(token) };
+                    return res.map_err(|_| RecvTimeoutError::Disconnected);
+                }
+
+                if backoff.is_complete() {
+                    break;
+                } else {
+                    backoff.snooze();
+                }
+            }
+
+            Context::with(|cx| {
+                // Prepare for blocking until a sender wakes us up.
+                let oper = Operation::hook(token);
+                self.receivers.register(oper, cx);
+
+                // Has the channel become ready just now?
+                if !self.is_empty() || self.is_disconnected() {
+                    let _ = cx.try_select(Selected::Aborted);
+                }
+
+                // Block the current thread.
+                let sel = cx.wait_until(deadline);
+
+                match sel {
+                    Selected::Waiting => unreachable!(),
+                    Selected::Aborted | Selected::Disconnected => {
+                        self.receivers.unregister(oper).unwrap();
+                        // If the channel was disconnected, we still have to check for remaining
+                        // messages.
+                    }
+                    Selected::Operation(_) => {}
+                }
+            });
+
+            if let Some(d) = deadline {
+                if Instant::now() >= d {
+                    return Err(RecvTimeoutError::Timeout);
+                }
+            }
+        }
+    }
+
+    /// Returns the current number of messages inside the channel.
+    pub fn len(&self) -> usize {
+        loop {
+            // Load the tail, then load the head.
+            let tail = self.tail.load(Ordering::SeqCst);
+            let head = self.head.load(Ordering::SeqCst);
+
+            // If the tail didn't change, we've got consistent values to work with.
+            if self.tail.load(Ordering::SeqCst) == tail {
+                let hix = head & (self.mark_bit - 1);
+                let tix = tail & (self.mark_bit - 1);
+
+                return if hix < tix {
+                    tix - hix
+                } else if hix > tix {
+                    self.cap - hix + tix
+                } else if (tail & !self.mark_bit) == head {
+                    0
+                } else {
+                    self.cap
+                };
+            }
+        }
+    }
+
+    /// Returns the capacity of the channel.
+    pub fn capacity(&self) -> Option<usize> {
+        Some(self.cap)
+    }
+
+    /// Disconnects the channel and wakes up all blocked receivers.
+    pub fn disconnect(&self) {
+        let tail = self.tail.fetch_or(self.mark_bit, Ordering::SeqCst);
+
+        if tail & self.mark_bit == 0 {
+            self.senders.disconnect();
+            self.receivers.disconnect();
+        }
+    }
+
+    /// Returns `true` if the channel is disconnected.
+    pub fn is_disconnected(&self) -> bool {
+        self.tail.load(Ordering::SeqCst) & self.mark_bit != 0
+    }
+
+    /// Returns `true` if the channel is empty.
+    pub fn is_empty(&self) -> bool {
+        let head = self.head.load(Ordering::SeqCst);
+        let tail = self.tail.load(Ordering::SeqCst);
+
+        // Is the tail equal to the head?
+        //
+        // Note: If the head changes just before we load the tail, that means there was a moment
+        // when the channel was not empty, so it is safe to just return `false`.
+        (tail & !self.mark_bit) == head
+    }
+
+    /// Returns `true` if the channel is full.
+    pub fn is_full(&self) -> bool {
+        let tail = self.tail.load(Ordering::SeqCst);
+        let head = self.head.load(Ordering::SeqCst);
+
+        // Is the head lagging one lap behind tail?
+        //
+        // Note: If the tail changes just before we load the head, that means there was a moment
+        // when the channel was not full, so it is safe to just return `false`.
+        head.wrapping_add(self.one_lap) == tail & !self.mark_bit
+    }
+}
+
+impl<T> Drop for Channel<T> {
+    fn drop(&mut self) {
+        // Get the index of the head.
+        let hix = self.head.load(Ordering::Relaxed) & (self.mark_bit - 1);
+
+        // Loop over all slots that hold a message and drop them.
+        for i in 0..self.len() {
+            // Compute the index of the next slot holding a message.
+            let index = if hix + i < self.cap {
+                hix + i
+            } else {
+                hix + i - self.cap
+            };
+
+            unsafe {
+                self.buffer.add(index).drop_in_place();
+            }
+        }
+
+        // Finally, deallocate the buffer, but don't run any destructors.
+        unsafe {
+            Vec::from_raw_parts(self.buffer, 0, self.cap);
+        }
+    }
+}
+
+/// Receiver handle to a channel.
+pub struct Receiver<'a, T: 'a>(&'a Channel<T>);
+
+/// Sender handle to a channel.
+pub struct Sender<'a, T: 'a>(&'a Channel<T>);
+
+impl<'a, T> SelectHandle for Receiver<'a, T> {
+    fn try_select(&self, token: &mut Token) -> bool {
+        self.0.start_recv(token)
+    }
+
+    fn deadline(&self) -> Option<Instant> {
+        None
+    }
+
+    fn register(&self, oper: Operation, cx: &Context) -> bool {
+        self.0.receivers.register(oper, cx);
+        self.is_ready()
+    }
+
+    fn unregister(&self, oper: Operation) {
+        self.0.receivers.unregister(oper);
+    }
+
+    fn accept(&self, token: &mut Token, _cx: &Context) -> bool {
+        self.try_select(token)
+    }
+
+    fn is_ready(&self) -> bool {
+        !self.0.is_empty() || self.0.is_disconnected()
+    }
+
+    fn watch(&self, oper: Operation, cx: &Context) -> bool {
+        self.0.receivers.watch(oper, cx);
+        self.is_ready()
+    }
+
+    fn unwatch(&self, oper: Operation) {
+        self.0.receivers.unwatch(oper);
+    }
+}
+
+impl<'a, T> SelectHandle for Sender<'a, T> {
+    fn try_select(&self, token: &mut Token) -> bool {
+        self.0.start_send(token)
+    }
+
+    fn deadline(&self) -> Option<Instant> {
+        None
+    }
+
+    fn register(&self, oper: Operation, cx: &Context) -> bool {
+        self.0.senders.register(oper, cx);
+        self.is_ready()
+    }
+
+    fn unregister(&self, oper: Operation) {
+        self.0.senders.unregister(oper);
+    }
+
+    fn accept(&self, token: &mut Token, _cx: &Context) -> bool {
+        self.try_select(token)
+    }
+
+    fn is_ready(&self) -> bool {
+        !self.0.is_full() || self.0.is_disconnected()
+    }
+
+    fn watch(&self, oper: Operation, cx: &Context) -> bool {
+        self.0.senders.watch(oper, cx);
+        self.is_ready()
+    }
+
+    fn unwatch(&self, oper: Operation) {
+        self.0.senders.unwatch(oper);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crossbeam-channel/src/flavors/list.rs
@@ -0,0 +1,657 @@
+//! Unbounded channel implemented as a linked list.
+
+use std::cell::UnsafeCell;
+use std::marker::PhantomData;
+use std::mem::{self, ManuallyDrop};
+use std::ptr;
+use std::sync::atomic::{self, AtomicPtr, AtomicUsize, Ordering};
+use std::time::Instant;
+
+use crossbeam_utils::{Backoff, CachePadded};
+
+use context::Context;
+use err::{RecvTimeoutError, SendTimeoutError, TryRecvError, TrySendError};
+use select::{Operation, SelectHandle, Selected, Token};
+use waker::SyncWaker;
+
+// TODO(stjepang): Once we bump the minimum required Rust version to 1.28 or newer, re-apply the
+// following changes by @kleimkuhler:
+//
+// 1. https://github.com/crossbeam-rs/crossbeam-channel/pull/100
+// 2. https://github.com/crossbeam-rs/crossbeam-channel/pull/101
+
+// Bits indicating the state of a slot:
+// * If a message has been written into the slot, `WRITE` is set.
+// * If a message has been read from the slot, `READ` is set.
+// * If the block is being destroyed, `DESTROY` is set.
+const WRITE: usize = 1;
+const READ: usize = 2;
+const DESTROY: usize = 4;
+
+// Each block covers one "lap" of indices.
+const LAP: usize = 32;
+// The maximum number of messages a block can hold.
+const BLOCK_CAP: usize = LAP - 1;
+// How many lower bits are reserved for metadata.
+const SHIFT: usize = 1;
+// Has two different purposes:
+// * If set in head, indicates that the block is not the last one.
+// * If set in tail, indicates that the channel is disconnected.
+const MARK_BIT: usize = 1;
+
+/// A slot in a block.
+struct Slot<T> {
+    /// The message.
+    msg: UnsafeCell<ManuallyDrop<T>>,
+
+    /// The state of the slot.
+    state: AtomicUsize,
+}
+
+impl<T> Slot<T> {
+    /// Waits until a message is written into the slot.
+    fn wait_write(&self) {
+        let backoff = Backoff::new();
+        while self.state.load(Ordering::Acquire) & WRITE == 0 {
+            backoff.snooze();
+        }
+    }
+}
+
+/// A block in a linked list.
+///
+/// Each block in the list can hold up to `BLOCK_CAP` messages.
+struct Block<T> {
+    /// The next block in the linked list.
+    next: AtomicPtr<Block<T>>,
+
+    /// Slots for messages.
+    slots: [Slot<T>; BLOCK_CAP],
+}
+
+impl<T> Block<T> {
+    /// Creates an empty block.
+    fn new() -> Block<T> {
+        unsafe { mem::zeroed() }
+    }
+
+    /// Waits until the next pointer is set.
+    fn wait_next(&self) -> *mut Block<T> {
+        let backoff = Backoff::new();
+        loop {
+            let next = self.next.load(Ordering::Acquire);
+            if !next.is_null() {
+                return next;
+            }
+            backoff.snooze();
+        }
+    }
+
+    /// Sets the `DESTROY` bit in slots starting from `start` and destroys the block.
+    unsafe fn destroy(this: *mut Block<T>, start: usize) {
+        // It is not necessary to set the `DESTROY bit in the last slot because that slot has begun
+        // destruction of the block.
+        for i in start..BLOCK_CAP - 1 {
+            let slot = (*this).slots.get_unchecked(i);
+
+            // Mark the `DESTROY` bit if a thread is still using the slot.
+            if slot.state.load(Ordering::Acquire) & READ == 0
+                && slot.state.fetch_or(DESTROY, Ordering::AcqRel) & READ == 0
+            {
+                // If a thread is still using the slot, it will continue destruction of the block.
+                return;
+            }
+        }
+
+        // No thread is using the block, now it is safe to destroy it.
+        drop(Box::from_raw(this));
+    }
+}
+
+/// A position in a channel.
+#[derive(Debug)]
+struct Position<T> {
+    /// The index in the channel.
+    index: AtomicUsize,